我有一个名为PAYMENT的表。在这个表中,我有一个用户ID、一个帐号、一个邮政编码和一个日期。我想找到所有用户的所有记录,每天有一个以上的付款与相同的账号。

更新:此外,应该有一个过滤器,只计算邮政编码不同的记录。

这是表格的样子:

| user_id | account_no | zip   |      date |
|       1 |        123 | 55555 | 12-DEC-09 | 
|       1 |        123 | 66666 | 12-DEC-09 |
|       1 |        123 | 55555 | 13-DEC-09 |
|       2 |        456 | 77777 | 14-DEC-09 |
|       2 |        456 | 77777 | 14-DEC-09 |
|       2 |        789 | 77777 | 14-DEC-09 |
|       2 |        789 | 77777 | 14-DEC-09 |

结果应该如下所示:

| user_id | count |
|       1 |     2 |

如何在SQL查询中表达这一点?我在考虑自连接,但出于某种原因,我的计数是错误的。


使用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

我不建议新手使用HAVING关键字,它本质上是用于遗留目的的。

我不清楚这张表的关键是什么(我想知道它是否完全标准化了?),因此我发现很难遵循您的规范:

我想找到所有用户的所有记录,有多个 每天支付相同的账号…此外,有 应该是一个过滤器,而不是只计算其邮政编码的记录 不同。

所以我采取了字面上的解释。

下面是更详细的,但可能更容易理解和维护(我已经使用了一个CTE表PAYMENT_TALLIES,但它可以是一个视图:

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
              );

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;

试试这个问题:

SELECT column_name
  FROM table_name
 GROUP BY column_name
HAVING COUNT(column_name) = 1;