5

我想计算每个用户在“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

4 回答 4

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

根据安德烈亚斯的评论进行编辑。

于 2012-08-01T16:21:02.120 回答
1

假设每个name->对都是唯一的,这将为您提供每个 namevalue值在 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

正如您会注意到的,我们还必须排除与自身相等的对。

但是,如果您想计算每个名称的值在 table 中任何值的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 演示

于 2012-08-01T19:32:15.357 回答
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 标签,我只是喜欢这个问题 ;-)

于 2012-08-01T16:48:15.737 回答
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
于 2012-08-01T16:56:24.020 回答