在连续日期对记录进行分组

时间:2017-09-22 12:15:51

标签: sql postgresql aggregate gaps-and-islands

如果我在Postgres中有下表:

order_dtls

Order_id    Order_date  Customer_name
-------------------------------------
1           11/09/17    Xyz
2           15/09/17    Lmn
3           12/09/17    Xyz
4           18/09/17    Abc
5           15/09/17    Xyz
6           25/09/17    Lmn
7           19/09/17    Abc

我想找回连续2天下订单的客户。 在上述情况下,XyzAbc客户应通过查询返回。

5 个答案:

答案 0 :(得分:1)

对于postgresql:

select distinct(Customer_name) from your_table
where exists 
    (select 1 from your_table t1 
    where 
    Customer_name = your_table.Customer_name and Order_date = your_table.Order_date+1 )

与MySQL相同,而不是your_table.Order_date+1使用:DATE_ADD(your_table.Order_date , INTERVAL 1 DAY)

答案 1 :(得分:1)

有很多方法可以做到这一点。使用EXISTS半联接,然后DISTINCTGROUP BY应该是最快的。

Postgres 语法:

SELECT DISTINCT customer_name
FROM   order_dtls o
WHERE  EXISTS (
   SELEST 1 FROM order_dtls
   WHERE  customer_name = o.customer_name
   AND    order_date = o.order_date + 1  -- simple syntax for data type "date" in Postgres!
   );

如果表格很大,请务必在(customer_name, order_date)上设置索引以使其快速 - 按此顺序索引项目。

澄清一下,因为Oto碰巧发布almost the same solution的速度要快一些:

DISTINCT是一个SQL构造,一个语法元素,而不是一个函数。 使用 DISTINCT (customer_name) 等括号。对DISTINCT ROW(customer_name) - 与DISTINCT无关的行构造函数来说是简短的 - 对于具有单个表达式的简单情况只是噪声,因为Postgres会自动删除单个元素的无意义行包装器。但是如果你包含多个这样的表达式,你会得到一个实际的行类型 - 实际上是一个匿名记录,因为没有给出行类型。绝对不是你想要的。

另外,请勿将DISTINCTDISTINCT ON (expr, ...)混淆。参见:

答案 2 :(得分:0)

这应该有效:

SELECT A.customer_name
    FROM order_dtls A
    INNER JOIN (SELECT customer_name, order_date FROM order_dtls) as B
    ON(A.customer_name = B.customer_name and Datediff(B.Order_date, A.Order_date) =1)
    group by A.customer_name

答案 3 :(得分:0)

我认为这样做的方法是在下一个日期将日期部分与itselft一起加入表格,并将其与Customer_name一起加入。 这样,您可以确保同一个customer_name连续2天完成订单。

对于MySQL:

SELECT distinct *
FROM order_dtls t1
    INNER JOIN order_dtls t2 on
            t1.Order_date = DATE_ADD(t2.Order_date, INTERVAL 1 DAY) and
            t1.Customer_name = t2.Customer_name

您应该使用Distinct关键字选择结果,以确保同一客户的显示次数不会超过1次。

答案 4 :(得分:0)

尝试类似......

SELECT `order_dtls`.*
FROM `order_dtls`
INNER JOIN `order_dtls` AS mirror
ON `order_dtls`.`Order_id` <> `mirror`.`Order_id`
AND `order_dtls`.`Customer_name` = `mirror`.`Customer_name`
AND DATEDIFF(`order_dtls`.`Order_date`, `mirror`.`Order_date`) = 1