我有一个令牌表
id | status
------------
1 | taken
1 | used
1 | deleted
2 | taken
2 | deleted
3 | taken
我需要计算使用或使用的令牌数量。 如果在未使用的情况下获取和删除令牌,则不应计算它。
所以sql会像......
SELECT count(*) if the id's status is not (taken & deleted)
上面示例中所需的已使用令牌数为2,为
id 1 has been taken used and deleted -> count it
id 3 has been taken -> count it
id 2 has been taken and deleted without being used -> do not count it
答案 0 :(得分:1)
有点冗长但有效且仍然可读和可维护:
SELECT COUNT(DISTINCT id)
FROM dbo.Token t
WHERE EXISTS
(
SELECT 1 FROM dbo.Token t1
WHERE t.id = t1.id
AND t1.status = 'used'
)
OR
(
EXISTS(
SELECT 1 FROM dbo.Token t1
WHERE t.id = t1.id
AND t1.status = 'taken'
)
AND NOT EXISTS(
SELECT 1 FROM dbo.Token t1
WHERE t.id = t1.id
AND t1.status = 'deleted'
)
)
答案 1 :(得分:0)
试试这个:
SELECT SUM(CASE WHEN (CHARINDEX('used', data.status) > 0) OR (data.status = 'taken') THEN 1 ELSE 0 END) as [count]
FROM
(
SELECT DISTINCT id, (SELECT STUFF((SELECT Distinct ',' + status
FROM token a
WHERE a.id = b.id
FOR XML PATH (''))
, 1, 1, '')) as status
FROM token b
) data
答案 2 :(得分:0)
使用聚合和having
子句获取符合条件的ID列表:
SELECT id
FROM token t
GROUP BY id
HAVING SUM(case when status = 'taken' then 1 else 0 end) > 0 or
SUM(case when status = 'used' then 1 else 0 end) > 0;
要获得计数,请使用子查询或CTE:
SELECT COUNT(*)
FROM (SELECT id
FROM token t
GROUP BY id
HAVING SUM(case when status = 'taken' then 1 else 0 end) > 0 or
SUM(case when status = 'used' then 1 else 0 end) > 0
) t
答案 3 :(得分:0)
你需要能够考虑所有这三个条件,所以一个天真的方法是将每个三个与一个案例陈述进行比较:
WITH grouped as
(
select id from #uses group by id
)
select grouped.id,
used =
CASE WHEN used.id is not null THEN 'YES'
WHEN taken.id is not null and deleted.id is null THEN 'YES'
ELSE 'NO'
END
from grouped
left join #uses taken on grouped.id = taken.id
and taken.use_status = 'taken'
left join #uses used on grouped.id = used.id
and used.use_status = 'used'
left join #uses deleted on grouped.id = deleted.id
and deleted.use_status = 'deleted'
只要满足条件,case语句就会停止,因此您只需要WHEN
和ELSE
来满足条件。
这是一种天真的方法,并假设您每个ID只有一行并使用状态类型。如果情况并非如此,你必须做一些额外的工作。
答案 4 :(得分:0)
如果已经使用并使用了令牌 - >不要算数
SELECT
SUM(DECODE(status, 'taken', 1, 0)) +
SUM(DECODE(status, 'used', 1, 0)) -
SUM(DECODE(status, 'deleted', 1, 0))
FROM
token t
WHERE
status <> 'used' OR
EXISTS(SELECT 1 FROM token t2 WHERE t2.id = t.id and t2.status = 'deleted')
如果已经使用并使用了令牌 - &gt;算上它
SELECT
COUNT(1)
FROM
token t
WHERE
status = 'taken' AND
(
EXISTS(SELECT 1 FROM token t2 WHERE t2.id = t.id and t2.status = 'used') OR
NOT EXISTS(SELECT 1 FROM token t2 WHERE t2.id = t.id and t2.status = 'deleted')
)
答案 5 :(得分:0)
回到这个问题,一个解决方案可能是使用Pivot
SELECT COUNT(id)
FROM (
SELECT id, status FROM Token
) src
PIVOT
(
COUNT(status) FOR status IN ([taken], [used], [deleted])
) pvt
WHERE (taken = 1 AND deleted = 0)OR (used = 1)