2

我有两张桌子。

一张表包含客户详细信息(即)

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

其他表包含订单表(即)

id,customerid(foreign key),ordervalue,orderdate

我需要获取八月份最近一个月(即)未订购的客户列表。我该怎么做。

这是我试过的查询

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
4

3 回答 3

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'
    );
于 2013-09-01T09:46:22.087 回答
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

但是,如果您想更准确地了解您想要上个月的订单的位置,即1st of last month to last date of last month从那时起,您可以使用以下命令:

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 的答案,该答案更有效。

于 2013-09-01T09:57:20.280 回答
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 小提琴演示

将此与 snyder 的答案进行比较,很清楚为什么在将列与过滤值进行比较之前在列上使用函数是不好的做法。

这是=>带有两个查询的 sql fiddle 演示。执行计划如下:

这个查询:

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))
于 2013-09-01T11:04:51.327 回答