SQL记录的复杂计数
我在编写查询时遇到问题,该查询在某些条件下可以查找唯一的计数/重复项。我试图一次从一个类似于此的表中获取计数:SQL记录的复杂计数,sql,sql-server,sql-server-2008-r2,Sql,Sql Server,Sql Server 2008 R2,我在编写查询时遇到问题,该查询在某些条件下可以查找唯一的计数/重复项。我试图一次从一个类似于此的表中获取计数: |-P_key-|-----email-----|-act_no-|--Client--| | 1 | joe@code.com | 1 | Jets | | 2 | bob@code.com | 2 | Jets | | 3 | sue@code.com | NULL | Jets | | 4 |
|-P_key-|-----email-----|-act_no-|--Client--|
| 1 | joe@code.com | 1 | Jets |
| 2 | bob@code.com | 2 | Jets |
| 3 | sue@code.com | NULL | Jets |
| 4 | joe@code.com | 1 | Bills |
| 5 | bob@code.com | 2 | Bills |
| 6 | bob@code.com | 2 | Giants |
| 7 | max@code.com | 2 | Giants |
| 8 | ben@code.com | 5 | Pats |
我需要的是客户的计数,如下所示:
每个客户端的总记录计数
跨客户端删除重复电子邮件的良好记录计数
删除客户内重复账号的良好记录计数
跨客户删除重复账号的良好记录计数
删除客户内空白账号的良好记录计数
其中,在总行数之后/从总行数中删除任何重复项
所以joe@code.com和bob@code.com从Jets客户端删除/不计入项目间的“善后/善后/唯一电子邮件”,因为它们存在于其他客户端上,留下1个电子邮件地址sue@code.com这是来自Jets客户端的,在其他客户端上不存在
同样对于内部客户机,对于巨人客户机,2号账户是唯一的账户号,因此我不想计算任何一条记录,不管2号账户是否在其他客户机上。请查看账户号对于自身内部的所有其他客户机是如何唯一的。然而,对于Jets客户端,在客户端中查找账号时,所有3个账号在客户端中都是唯一的,但并非在所有客户端中都是唯一的,只有空值在所有客户端中都是唯一的。因此,在3个Jet账户中,3个在客户内部良好,但只有1个在客户之间良好
我希望实现的结果如下所示,尽管最终数据不一定需要如此旋转:
| | Jets | Bills | Giants | Pats |
| Total emails | 3 | 2 | 2 | 1 |
| good after unique emails across clients | 1 | 0 | 1 | 1 |
| good after unique account_no across clients | 1 | 0 | 0 | 1 |
| good after unique account_no within clients | 3 | 2 | 0 | 1 |
| good after blank account_no within clients | 2 | 0 | 0 | 0 |
或
同样值得注意的是,如果我想在客户端之外添加另一个层,例如客户端中代理的计数,那么这将是在客户端上向group by添加另一个字段,我该如何处理呢
我在想一种方法是使用where not exists语句,例如:
SELECT COUNT(x.act_no)
FROM x
WHERE NOT EXISTS (SELECT 'x' FROM t WHERE t.act_no = x.act_no)
AND x.client = 'Jets'
然而,我希望能够在一个查询中返回所有计数,而不是在可能的情况下拼凑出来
提前感谢您的帮助 不完全确定我是否正确解释了聚合规则,但下面是我的想法。这是一个垂直的结果,如果你希望它是水平的,你可以旋转
SELECT Client, result, CountType
FROM (SELECT Client, COUNT(*) AS result, 'Total emails' AS CountType
FROM ComplexCounting
GROUP BY Client
UNION
SELECT Client, COUNT(*) AS result, 'good after unique emails across clients' AS CountType
FROM ComplexCounting
WHERE (NOT EXISTS
(SELECT Id, email, act_no, Client
FROM ComplexCounting AS c
WHERE (Client <> ComplexCounting.Client) AND (email = ComplexCounting.email)))
GROUP BY Client
UNION
SELECT Client, COUNT(*) AS result, 'good after unique account_no across clients' AS CountType
FROM ComplexCounting
WHERE (NOT EXISTS
(SELECT Id, email, act_no, Client
FROM ComplexCounting AS c
WHERE (Client <> ComplexCounting.Client) AND (act_no = ComplexCounting.act_no)))
GROUP BY Client
UNION
SELECT Client, COUNT(*) AS result, 'good after unique account_no within clients' AS CountType
FROM ComplexCounting
WHERE (NOT EXISTS
(SELECT Id, email, act_no, Client
FROM ComplexCounting AS c
WHERE (Client = ComplexCounting.Client) AND (act_no = ComplexCounting.act_no) AND (Id <> ComplexCounting.Id)))
GROUP BY Client
UNION
SELECT Client, COUNT(DISTINCT act_no) AS result, 'good after blank account_no within clients' AS CountType
FROM ComplexCounting
WHERE EXISTS
(SELECT Id, email, act_no, Client
FROM ComplexCounting AS c
WHERE (act_no IS NULL) AND (Client = ComplexCounting.Client)) AND (act_no IS NOT NULL)
GROUP BY Client) AS Results
ORDER BY CountType
从多个选择中拼凑起来可能是最清晰的:
DECLARE @tbl TABLE (id INT, email VARCHAR(256), act_no INT NULL, client VARCHAR(10))
INSERT INTO @tbl VALUES
( 1 , 'joe@code.com' , 1 , 'Jets' )
,( 2 , 'bob@code.com' , 2 , 'Jets' )
,( 3 , 'sue@code.com' , NULL , 'Jets' )
,( 4 , 'joe@code.com' , 1 , 'Bills' )
,( 5 , 'bob@code.com' , 2 , 'Bills' )
,( 6 , 'bob@code.com' , 2 , 'Giants' )
,( 7 , 'max@code.com' , 2 , 'Giants' )
,( 8 , 'ben@code.com' , 5 , 'Pats' )
SELECT 'Total emails',client, COUNT(*)
FROM @tbl
GROUP BY client
SELECT 'good after unique emails across clients',client, COUNT(*)
FROM @tbl a
WHERE NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.email=a.email AND b.client <> a.client)
GROUP BY client
SELECT 'good after unique account_no across clients',client, COUNT(*)
FROM @tbl a
WHERE NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.act_no=a.act_no AND b.client <> a.client)
GROUP BY client
SELECT 'good after unique account_no within clients',client, COUNT(*)
FROM @tbl a
WHERE NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.act_no=a.act_no AND b.client = a.client GROUP BY b.act_no,b.client HAVING COUNT(*) > 1)
GROUP BY client
然后可以合并结果。您还可以从客户机列表中左键联接,以确保显示空计数
但是,您也可以非常简洁地一次完成这一切。请原谅别名过长
;WITH cte AS (
SELECT client
,CASE WHEN NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.email=a.email AND b.client <> a.client) THEN 1 ELSE 0 END [good after unique emails across clients]
,CASE WHEN NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.act_no=a.act_no AND b.client <> a.client) THEN 1 ELSE 0 END [good after unique account_no across clients]
,CASE WHEN NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.act_no=a.act_no AND b.client = a.client GROUP BY b.act_no,b.client HAVING COUNT(*) > 1) THEN 1 ELSE 0 END [good after unique account_no within clients]
FROM @tbl a
)
SELECT client
,COUNT(*) [Total emails]
,SUM([good after unique emails across clients]) [good after unique emails across clients]
,SUM([good after unique account_no across clients]) [good after unique account_no across clients]
,SUM([good after unique account_no within clients]) [good after unique account_no within clients]
FROM cte a
GROUP BY client
注意,我取消了“客户中没有空白账户后的良好状态”的选项,因为我认为您可以轻松添加该选项。Define after。请注意,ID是自动生成的这一事实并不能保证顺序,特别是在以后使用新信息更新行的情况下。最好考虑一个ID的实际值是随机的,没有内在的价值。您的标准也有点不透明-到目前为止,您尝试了什么来帮助我们了解您的目标?感谢您的回答,我已经用一个我正在尝试的示例更新了我的问题,希望以后能更好地定义
;WITH cte AS (
SELECT client
,CASE WHEN NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.email=a.email AND b.client <> a.client) THEN 1 ELSE 0 END [good after unique emails across clients]
,CASE WHEN NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.act_no=a.act_no AND b.client <> a.client) THEN 1 ELSE 0 END [good after unique account_no across clients]
,CASE WHEN NOT EXISTS (SELECT 1 FROM @tbl b WHERE b.act_no=a.act_no AND b.client = a.client GROUP BY b.act_no,b.client HAVING COUNT(*) > 1) THEN 1 ELSE 0 END [good after unique account_no within clients]
FROM @tbl a
)
SELECT client
,COUNT(*) [Total emails]
,SUM([good after unique emails across clients]) [good after unique emails across clients]
,SUM([good after unique account_no across clients]) [good after unique account_no across clients]
,SUM([good after unique account_no within clients]) [good after unique account_no within clients]
FROM cte a
GROUP BY client