SQL:查找行之间的差异

时间:2012-08-01 16:13:38

标签: mysql sql group-by distinct

我想计算每个用户在彼此的'5'内有多少行。

例如,Don-501和Don-504应计算在内,而Don-501和Don-1600不应计算在内。

开始:

Name        value
_________   ______________
Don         1235
Don         6012
Don         6014
Don         6300
James       9000
James       9502
James       9600
Sarah       1110
Sarah       1111
Sarah       1112
Sarah       1500
Becca       0500
Becca       0508
Becca       0709

完成:

Name            difference_5
__________      _____________
Don             1
James           0
Sarah           2
Becca           0

4 个答案:

答案 0 :(得分:2)

ABS()函数与子查询中的自联接结合使用:

所以,比如:

SELECT name, COUNT(*) / 2 AS difference_5
FROM (
  SELECT a.name name, ABS(a.value - b.value) 
  FROM  tbl a JOIN tbl b USING(name)
  WHERE ABS(a.value - b.value) BETWEEN 1 AND 5
) AS t GROUP BY name

根据Andreas的评论编辑。

答案 1 :(得分:1)

假设每个name - > value对是唯一的,这将为您提供值在5 每个名称 的范围内的次数:

SELECT    a.name, 
          COUNT(b.name) / 2 AS difference_5
FROM      tbl a
LEFT JOIN tbl b ON a.name = b.name AND 
                   a.value <> b.value AND
                   ABS(a.value - b.value) <= 5
GROUP BY  a.name

正如您将注意到的那样,我们还必须排除与自己相等的对。

但是,如果您想计算每个名称的值在表 中 任意值的5个范围内的次数,您可以使用:

SELECT    a.name,
          COUNT(b.name) / 2 AS difference_5
FROM      tbl a
LEFT JOIN tbl b ON NOT (a.name = b.name AND a.value = b.value) AND
                   ABS(a.value - b.value) <= 5
GROUP BY  a.name

有关这两种解决方案,请参阅SQLFiddle Demo

答案 2 :(得分:0)

因为OP也想要零计数,我们需要一个自左连接。如果一个人有两个完全相同的值,则需要额外的逻辑,这些也应该只计算一次。

WITH cnts AS (
        WITH pair AS (
                SELECT t1.zname,t1.zvalue
                FROM ztable t1
                JOIN ztable t2
                ON t1.zname = t2.zname
                WHERE ( t1.zvalue < t2.zvalue
                        AND t1.zvalue >= t2.zvalue - 5 )
                OR (t1.zvalue = t2.zvalue AND t1.ctid < t2.ctid)
                )
        SELECT DISTINCT zname
        , COUNT(*) AS znumber
        FROM pair
        GROUP BY zname
        )
, names AS (
        SELECT distinct zname  AS zname
        FROM ztable
        GROUP BY zname
        )
SELECT n.zname
        , COALESCE(c.znumber,0) AS znumber
FROM names n
LEFT JOIN cnts c ON n.zname = c.zname
        ;

结果:

DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
INSERT 0 14
 zname | znumber 
-------+---------
 Sarah |       3
 Don   |       1
 Becca |       0
 James |       0
(4 rows)

注意:对不起CTE,我没见过mysql标签,我只是喜欢这个问题; - )

答案 3 :(得分:0)

SELECT
    A.Name,
    SUM(CASE WHEN (A.Value < B.Value) AND (A.Value >= B.Value - 5) THEN 1 ELSE 0 END) Difference_5
FROM
    tbl A INNER JOIN
    tbl B USING(Name)
GROUP BY
    A.Name