2013-09-01 118 views
2

我有兩個表。加入兩個不匹配行的表

一個表包含客戶信息(即)

id(customerid--primary key),name,email,phonenumber 

與其他表包含順序表(IE)

id,customerid(foreign key),ordervalue,orderdate 

我需要得到誰沒有下令最後一個客戶名單8月份(即)。我該怎麼做。

這是我試圖

select a.id,a.name,b.order_date from customers a 
left join orders b 
on a.id = b.customer_id 
where b.order_date is null 

回答

3

這個查詢將提取那些誰沒有下令past one month from today客戶查詢:

SELECT a.id, a.name 
FROM customers a 
WHERE NOT EXISTS(SELECT * 
     FROM orders b 
     WHERE b.cid = a.id AND 
     orderdate BETWEEN now()- '1 month'::interval 
     AND now()); 

這裏是SQLfiddle

然而,如果你想要更精確地定位上個月的訂單,即從01開始那麼你可以使用這個:

SELECT a.id, a.name 
FROM customers a 
WHERE NOT EXISTS(SELECT * 
     FROM orders b 
     WHERE b.cid = a.id AND 
     to_char(orderdate, 'Mon YYYY') = 
        to_char(now()- '1 month'::interval, 'Mon YYYY')); 

這裏是SQLfiddle

編輯

也請看看Roman Pekar's答案是更有效的。

+0

好的今天是'sep 1'我需要取到'31 8月'我怎麼修改它 – overflow

+0

你不需要修改它,第二個查詢將做到這一點!檢查sql小提琴。 –

+0

感謝工作正常。 – overflow

3
SELECT * 
FROM customers c 
WHERE NOT EXISTS (
    SELECT * 
    FROM orders nx 
    WHERE nx.customer_id = c.id 
    AND nx.order_date BETWEEN '2013-08-01' AND '2013-08-31' 
    ); 
+0

你已硬編碼查詢。 –

+0

是的。它使讀起來更容易,OP的問題似乎在反連接中,而不是在範圍選擇中。不過,可以改變它以取決於當前的日期。 – wildplasser

1

如果您對orderdate指標,並希望使用這個指標,我建議使用此查詢(date_trunc功能是很方便的找到當月的第一天,和前一個月的第一天):

select c.id, c.name 
from customers as c 
where 
    not exists (
     select * 
     from orders as o 
     where 
      o.cid = c.id and 
      o.orderdate >= date_trunc('month', (now() - '1 month'::interval)::timestamp) and 
      o.orderdate < date_trunc('month', now()::timestamp) 
    ) 

=> sql fiddle demo

將這個與snyder的答案進行比較,很明顯爲什麼在將它與過濾器值進行比較之前在列上使用函數是不好的做法。

這裏的=> sql fiddle demo有兩個查詢。執行計劃:

這個查詢:

Nested Loop Anti Join (cost=0.02..2598.74 rows=160 width=222) 
-> Seq Scan on customers c (cost=0.00..13.20 rows=320 width=222) 
-> Index Only Scan using ix_orders on orders o (cost=0.02..8.07 rows=1 width=4) 
Index Cond: ((cid = c.id) AND (orderdate >= date_trunc('month'::text, ((now() - '1 mon'::interval))::timestamp without time zone)) AND (orderdate < date_trunc('month'::text, (now())::timestamp without time zone))) 

斯奈德:

Hash Anti Join (cost=30468.50..30523.40 rows=160 width=222) 
Hash Cond: (a.id = b.cid) 
-> Seq Scan on customers a (cost=0.00..13.20 rows=320 width=222) 
-> Hash (cost=30406.00..30406.00 rows=5000 width=4) 
-> Seq Scan on orders b (cost=0.00..30406.00 rows=5000 width=4) 
Filter: (to_char((orderdate)::timestamp with time zone, 'Mon YYYY'::text) = to_char((now() - '1 mon'::interval), 'Mon YYYY'::text)) 
+0

+1爲答案,這個查詢確實比我的好。 –