我想计算每个用户在彼此的'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
答案 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