我遇到了编写查询的问题,该查询可以在特定条件下查找唯一计数/重复项。我试图从一个类似于这个的表中一次得到计数:
|-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 |
我需要的是客户的计数如下:
从总行数开始/之后删除任何重复项。
因此,来自Jets客户端的joe@code.com和bob@code.com被删除/不计入好/之后/来自项目中的独特电子邮件,因为它们存在于其他客户端上,留下1个电子邮件地址( sue@code.com)来自Jets客户端,在其他客户端上不存在。
对于内部客户端,对于Giants客户端,acct_no 2是唯一的acct_no,所以我不想计算任何一条记录,无论acct_no 2是否在其他客户端上(请参阅acct_no对于其他所有客户端的唯一性)客户内部)。而在跨客户端查找acct_nos时,对于Jets客户端,所有3个acct_no在客户端中都是唯一的,但不是在所有客户端上(只有空值在所有客户端中是唯一的)。因此,在3台喷气机中,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 |
OR
| | tot unique emails | good emails | etc...
| Jets | 3 | 1 |
|Bills | 2 | 0 |
| Giants | 2 | 1 |
| Pats | 1 | 1 |
另外值得注意的是,如果我想添加另一个层而不是客户端,例如客户端中代理的计数,那么它将在客户端上向该组添加另一个字段,我该如何处理它?</ p>
我在想一种方法是使用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'
但是,我希望能够在一个查询中返回所有计数,而不是在可能的情况下将其拼凑出来。
提前感谢您提供任何帮助!
答案 0 :(得分:0)
不完全确定我是否正确地解释了聚合规则,但这就是我想出的。这是一个垂直结果,如果你希望它是水平的,你可以转动它。
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
答案 1 :(得分:0)
从多个选项中将它拼凑起来可能是最清楚的:
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
然后你可以UNION结果。您还可以从客户列表中LEFT JOIN以确保显示空计数。
但是,您也可以相当简洁地一次完成所有操作。请原谅过长的别名。
;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
注意,我在客户的空白account_no之后离开了&#39;因为我认为你可以很容易地添加它。