1

我在处理涉及下表的复杂查询时遇到了一些问题。假设时间使用内置的 sqlite 时间戳数据类型。

我正在尝试退回在第一次购买后 4 小时内第二次购买的客户,如果是在 2 小时内,则必须来自不同的商店。

我在思考如何参考特定行来比较第一次购买和第二次购买时遇到了麻烦。

购买

purchase_id | customer_id | store_id | purchase_time
     1             1            1      2009-01-27 10:00:00.0
     2             1            2      2009-01-27 10:30:00.0
     3             2            1      2009-01-27 10:00:00.0
     4             2            1      2009-01-27 10:30:00.0
     5             3            1      2009-01-27 10:00:00.0
     6             3            2      2009-01-27 16:00:00.0
     7             4            3      2009-01-27 10:00:00.0
     8             4            3      2009-01-27 13:00:00.0

商店

store_id | misc columns...
    1
    2
    3

顾客

customer_id | f_name
     1         name1
     2         name2
     3         name3
     4         name4

name1, name4在这种情况下,正确的回报将是。

4

1 回答 1

2

您将要加入购买表本身,然后选择两个标准之一。

这里唯一真正的技巧是将不同的时间标准制定为:

  1. 在不同商店购买的时间少于 2 小时。
  2. 在 2 到 4 小时之间进行的购买,独立于store_id.

这两者显然适用于相同的customer_id.

所以,我们有:

select p1.purchase_id purchase_1, 
       p2.purchase_id purchase_2,
       c.name,
       p1.customer_id customer
from purchases p1
join purchases p2 on
p1.customer_id = p2.customer_id
join customer c on c.customer_id = p1.customer_id
where p1.purchase_time < p2.purchase_time
 and (
        (
        addtime(p1.purchase_time,'2:00:00') >= p2.purchase_time
        and p1.store_id <> p2.store_id
        )
      or
        (
        addtime(p1.purchase_time,'2:00:00') < p2.purchase_time
        and addtime(p1.purchase_time,'4:00:00') >= p2.purchase_time
        )
     )

它通过 customer_id 将购买连接到自身,首先检查您是否将早期购买与以后购买进行比较,然后在OR编辑的标准中应用两个不同的标准。

我发现最容易进行时间比较addtime(),然后比较结果。其他人可能更喜欢其他方式。

SQL 小提琴在这里: http ://sqlfiddle.com/#!2/14dda/2

结果:

PURCHASE_1  PURCHASE_2        NAME        CUSTOMER
1           2                 name1       1
7           8                 name4       4

--

编辑:也许,您可以通过将p1.purchase_time < p2.purchase_timeup 移入join子句来提高效率。尽管针对少量数据的执行计划是相同的,但对于大量数据,这可能会更快。您希望优化器p1.purchase_time > p2.purchase_time在进行更昂贵的比较之前消除所有这些情况。但这有点超出了编写此查询的方法的基本问题。

于 2012-06-10T16:46:31.000 回答