用于查找 count > 1 的记录的 SQL 查询
Posted
技术标签:
【中文标题】用于查找 count > 1 的记录的 SQL 查询【英文标题】:SQL query for finding records where count > 1 【发布时间】:2011-11-01 08:35:53 【问题描述】:我有一个名为PAYMENT
的表。在这张表中,我有一个用户 ID、一个帐号、一个邮政编码和一个日期。我想查找所有使用相同帐号每天进行一次以上付款的用户的所有记录。
更新:此外,应该有一个过滤器,而不是只计算邮政编码不同的记录。
这就是表格的样子:
|用户 ID |帐户号 |拉链 |日期 | | 1 | 123 | 55555 | 2009 年 12 月 12 日 | | 1 | 123 | 66666 | 2009 年 12 月 12 日 | | 1 | 123 | 55555 | 2009 年 12 月 13 日 | | 2 |第456章77777 | 09 年 12 月 14 日 | | 2 |第456章77777 | 09 年 12 月 14 日 | | 2 |第789章77777 | 09 年 12 月 14 日 | | 2 |第789章77777 | 09 年 12 月 14 日 |结果应该类似于:
|用户 ID |计数 | | 1 | 2 |您将如何在 SQL 查询中表达这一点?我在考虑自我加入,但由于某种原因我的计数是错误的。
【问题讨论】:
【参考方案1】:使用 HAVING 子句和 GROUP By 使行唯一的字段
下面会找到
所有使用相同帐号每天进行一次以上付款的用户
SELECT
user_id ,
COUNT(*) count
FROM
PAYMENT
GROUP BY
account,
user_id ,
date
HAVING
COUNT(*) > 1
更新 如果您只想包含具有不同 ZIP 的那些,您可以先获取不同的集合,然后执行 HAVING/GROUP BY
SELECT
user_id,
account_no ,
date,
COUNT(*)
FROM
(SELECT DISTINCT
user_id,
account_no ,
zip,
date
FROM
payment
)
payment
GROUP BY
user_id,
account_no ,
date
HAVING COUNT(*) > 1
【讨论】:
在他的结果中注意到2
的计数为4
- 我认为你会想要丢弃Account_no
分组。
等一下,我认为原文是正确的“所有用户每天使用相同的帐号进行多次付款。”
它是这么说的,但他的结果却不是这样。也许两个版本都有注释。
感谢您的回复。我认为应该这样做。如果我现在想添加另一个过滤器来检查同一日期的帐单邮政编码(同一张表,不同列)是否不同,我将如何修改此查询?
我无法解析示例输出。如果我们删除 Account,我们会得到三行。如果我们同时删除日期和帐户,我们将得到两行 1,3 和 2,4。所以我要继续相信输出的单词【参考方案2】:
试试这个查询:
SELECT column_name
FROM table_name
GROUP BY column_name
HAVING COUNT(column_name) = 1;
【讨论】:
整洁,但这并不能回答问题【参考方案3】:create table payment(
user_id int(11),
account int(11) not null,
zip int(11) not null,
dt date not null
);
insert into payment values
(1,123,55555,'2009-12-12'),
(1,123,66666,'2009-12-12'),
(1,123,77777,'2009-12-13'),
(2,456,77777,'2009-12-14'),
(2,456,77777,'2009-12-14'),
(2,789,77777,'2009-12-14'),
(2,789,77777,'2009-12-14');
select foo.user_id, foo.cnt from
(select user_id,count(account) as cnt, dt from payment group by account, dt) foo
where foo.cnt > 1;
【讨论】:
【参考方案4】:我不会为新手推荐HAVING
关键字,它是essentially for legacy purposes。
我不清楚这张表的关键是什么(我想知道是fully normalized吗?),因此我很难遵循您的规范:
我想查找拥有多个记录的所有用户的所有记录 每天使用相同的帐号付款...此外,还有 应该是一个过滤器,而不是只计算邮政编码为的记录 不同。
所以我采取了字面解释。
以下内容更冗长,但可能更易于理解和维护(我使用CTE 表PAYMENT_TALLIES
,但它可能是VIEW
:
WITH PAYMENT_TALLIES (user_id, zip, tally)
AS
(
SELECT user_id, zip, COUNT(*) AS tally
FROM PAYMENT
GROUP
BY user_id, zip
)
SELECT DISTINCT *
FROM PAYMENT AS P
WHERE EXISTS (
SELECT *
FROM PAYMENT_TALLIES AS PT
WHERE P.user_id = PT.user_id
AND PT.tally > 1
);
【讨论】:
当可读性/可维护性是主要关注点时,CTE/子查询方法绝对值得使用。不过,我不同意HAVING
是“遗留”——它在 10 年后仍然被广泛使用,并且是一种非常有用的速记方式,可以避免您的示例中冗长的需要。
HAVING 对我来说似乎更具可读性,WHERE EXISTS 可能更快...以上是关于用于查找 count > 1 的记录的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章