Sql 返回时差超过阈值的行的查询

Sql 返回时差超过阈值的行的查询,sql,postgresql,datetime,join,row,Sql,Postgresql,Datetime,Join,Row,这是一个奇怪的问题。我不知道这是否可行 假设我有下表: person | product | trans | purchase_date -------+----------+--------+--------------- jim | square | aaaa | 2013-03-04 00:01:00 sarah | circle | aaab | 2013-03-04 00:02:00 john | square | aac1 | 2013-03-

这是一个奇怪的问题。我不知道这是否可行

假设我有下表:

person | product  | trans  | purchase_date
-------+----------+--------+---------------
jim    | square   | aaaa   | 2013-03-04 00:01:00
sarah  | circle   | aaab   | 2013-03-04 00:02:00
john   | square   | aac1   | 2013-03-04 00:03:00
john   | circle   | aac2   | 2013-03-04 00:03:10
jim    | triangle | aad1   | 2013-03-04 00:04:00
jim    | square   | abcd   | 2013-03-04 00:05:00
sarah  | square   | efgh   | 2013-03-04 00:07:00
jim    | circle   | ijkl   | 2013-03-04 00:22:00
sarah  | circle   | mnop   | 2013-03-04 00:24:00
sarah  | square   | qrst   | 2013-03-04 00:26:00
sarah  | circle   | uvwx   | 2013-03-04 00:44:00
我需要知道任何人购买的正方形和圆形(或圆形和正方形)之间的差异何时超过10分钟。理想情况下,我也想知道这种差异,但这不是必需的

因此,我需要的是:

person | product  | trans  | purchase_date
-------+----------+--------+---------------
jim    | square   | abcd   | 2013-03-04 00:05:00
jim    | circle   | ijkl   | 2013-03-04 00:22:00
sarah  | square   | efgh   | 2013-03-04 00:07:00
sarah  | circle   | mnop   | 2013-03-04 00:24:00
sarah  | square   | qrst   | 2013-03-04 00:26:00
sarah  | circle   | uvwx   | 2013-03-04 00:44:00
这将每天运行,因此我将添加一个“where”子句以确保查询不会失控。此外,我知道可能会出现多个交易(比如,购买一个圆圈的时间间隔为20分钟,然后购买一个正方形的时间间隔为20分钟,然后再购买一个圆圈的时间间隔为20分钟,这意味着有两个实例的时差超过10分钟)


有什么建议吗?我在postgres 8.1.23上

你可以尝试用这样一个“on”子句将表格连接到它自己:

SELECT a.Person, CAST((DATEDIFF(mi, b.purchaseDateb a.purchaseDate)/60.0) AS Decimal) AS TimeDiff, a.Product, b.Product FROM <TABLE> a
JOIN <TABLE> b
ON a.Person = b.Person AND b.purchaseDate > a.purchaseDate
WHERE
(a.Product = 'Circle' AND b.Product = 'Square')
OR
(a.Product = 'Square' AND b.Product = 'Circle')
选择a.Person,CAST((DATEDIFF(mi,b.purchaseDateb a.purchaseDate)/60.0)作为十进制)作为TimeDiff,a.Product,b.Product FROM a
加入b
在a.Person=b.Person和b.purchaseDate>a.purchaseDate上
哪里
(a.乘积=‘圆’和b.乘积=‘方’)
或
(a.乘积=‘正方形’和b.乘积=‘圆形’)
通过将表连接到表本身,您可以得到将同一个人的两次购买合并在一起的行。通过将其限制为“b.purchaseDate>a.purchaseDate”,可以防止行与其匹配。然后,您可以简单地检查购买的不同产品

时差是最后一个棘手的部分。我上面所说的是基于我找到的答案。它看起来应该可以工作,如果输出的内容对您不起作用,您可以使用一些变体

您需要在WHERE语句中添加一个子句,该子句使用相同的DATEDIFF函数来测试time>10分钟,但这不会带来太大的挑战

请注意,这不会完全返回您在问题中的内容-这将包括Jim第一笔交易的一行以及Jim第二笔购买的一行。两者都将匹配到同一个圆,您将获得两次(ijkl abcd和ijkl aaaa)。感谢xQbert的评论指出这一点。

--

  • 您想知道在同一天购买时的分钟数差异。如果日期无关紧要,则删除where子句
  • 您只想在购买日期之后,而不是之前,将圆圈的注意事项平方化。 .

    选择A.人员、A.产品、A.运输、A.采购日期、B.采购日期、,
    小时差异*60+日期部分(“分钟”,B.购买日期-A.购买日期)作为分钟差异
    从你的桌子上
    左键连接表B
    在某人身上=在某人身上
    和((A.product='square'和b.product='circle'))
    或者(A.Product='circle'和b.Product='square'))
    和A.购买最新的现代解决方案
    对于现代Postgres(8.4或更高版本),您可以使用获得每组的连续编号。然后,您可以左键连接到上一行和下一行,并查看它们是否符合条件。瞧

    WITH x AS (
       SELECT *
             ,row_number() OVER (PARTITION BY person ORDER BY purchase_date) AS rn
       FROM   tbl
       WHERE  product IN ('circle', 'square')
       )
    SELECT x.person, x.product, x.trans, x.purchase_date
    FROM   x
    LEFT   JOIN x y ON y.person = x.person AND y.rn = x.rn + 1
    LEFT   JOIN x z ON z.person = x.person AND z.rn = x.rn - 1
    WHERE (y.product <> x.product
           AND y.purchase_date > x.purchase_date + interval '10 min')
       OR (z.product <> x.product
           AND z.purchase_date < x.purchase_date - interval '10 min')
    ORDER  BY x.person, x.purchase_date;
    
    然后,同样的
    选择
    应该可以工作:

    SELECT x.person, x.product, x.trans, x.purchase_date
    FROM   x
    LEFT   JOIN x y ON y.person = x.person AND y.rn = x.rn + 1
    LEFT   JOIN x z ON z.person = x.person AND z.rn = x.rn - 1
    WHERE (y.product <> x.product
           AND y.purchase_date > x.purchase_date + interval '10 min')
       OR (z.product <> x.product
           AND z.purchase_date < x.purchase_date - interval '10 min')
    ORDER  BY x.person, x.purchase_date;
    
    选择x.person、x.product、x.trans、x.purchase\u date
    从x
    在y.person=x.person和y.rn=x.rn+1上左连接x y
    在z.person=x.person和z.rn=x.rn-1上左连接x z
    其中(y.产品x.产品)
    y.购买日期>x.购买日期+间隔“10分钟”)
    或(z.产品x.产品)
    和z.购买日期
    考虑到你的标准,为什么吉姆的tran aaaa广场不回来?@xQbert如果发生这种情况,我很好。不能保证按顺序插入正方形和圆形(对吗?)。但是,因为在吉姆购买另一个“正方形”之前,这个“正方形”没有对应的“圆圈”,所以我把它从列表中删除了。应该有1:1的正方形:圆形。如果有一个是无与伦比的,我很高兴知道。我有一些应该有效的东西,但它将包括xQbert指出的结果。您必须将事务ID添加到结果集中以过滤掉这些事务ID(这可能在代码中比在SQL中更好)。现代版本使这变得容易多了。@ErwinBrandstetter我很想升级,但8.1是我们目前得到的,这不取决于我。我尝试了这个,结果查询的内存用完了(甚至把它缩小到一天的数据量)。仅供其他人参考,postgres生成时差的方法(我正在使用)是abs(DATE_PART('epoch',a.purchase_DATE-b.purchase_DATE))@jasonClose:老实说,如果您在这方面的内存不足,那么提取这些数据并用代码运行分析可能会更容易。这个查询不应该占用大量内存,除非数据量很大。这一点很好。我会提高记忆力和博士后,看看这是否有帮助。数据并没有那么大。我们每天可能会得到10万个数据点。这也会匹配同一个人的任何一行和匹配的产品,而不仅仅是相邻的一行。导致交叉连接(由于您的附加条件限制在同一天),这是非常昂贵的废话。winner winner鸡肉晚餐。就是这样。我使用了8.1解决方案,效果非常好。我缩短了查询以删除z连接,因为x和y上的连接为我提供了所需的一切。这个表一天有125k行(我回去检查了一下),所以自己加入这个表太费时了。这就成功了。如果我没有弄错的话,如果我没有在8.1?Thanx上为所有的鸡计算,滞后函数也可以工作。你的真实情况可能不同。但是对于所问的问题,
    z
    是必不可少的。如果没有它,最后一行将从每一系列符合条件的行中删除-如本文所示。
    CREATE TEMP SEQUENCE s;
    
    CREATE TEMP TABLE x AS
    SELECT *, nextval('s') AS rn  -- get row-numbers from sequence
    FROM  (
       SELECT *
       FROM   tbl
       WHERE  product IN ('circle', 'square')
       ORDER  BY person, purchase_date  -- need to order in a subquery first!
       ) a;
    
    SELECT x.person, x.product, x.trans, x.purchase_date
    FROM   x
    LEFT   JOIN x y ON y.person = x.person AND y.rn = x.rn + 1
    LEFT   JOIN x z ON z.person = x.person AND z.rn = x.rn - 1
    WHERE (y.product <> x.product
           AND y.purchase_date > x.purchase_date + interval '10 min')
       OR (z.product <> x.product
           AND z.purchase_date < x.purchase_date - interval '10 min')
    ORDER  BY x.person, x.purchase_date;