Mysql 根据条件从表中选择计数
我有这样一个审计表: 我需要得到用户和他们签署的文档数量。一个用户可以对文档进行n次签名,但当计数时,该用户已对文档进行了1次签名。如果在一个文档上调用了reject,则该文档不考虑所有用户先前的reject。此外,查询性能非常重要,因为有数百万个条目 结果将是: 这是你想要的吗Mysql 根据条件从表中选择计数,mysql,sql,sql-server,Mysql,Sql,Sql Server,我有这样一个审计表: 我需要得到用户和他们签署的文档数量。一个用户可以对文档进行n次签名,但当计数时,该用户已对文档进行了1次签名。如果在一个文档上调用了reject,则该文档不考虑所有用户先前的reject。此外,查询性能非常重要,因为有数百万个条目 结果将是: 这是你想要的吗 select user, sum(case when event = 'sign' then 1 else 0 end) as num_signs from audittable group by user; 对不起
select user, sum(case when event = 'sign' then 1 else 0 end) as num_signs
from audittable
group by user;
对不起,如果有错别字。我不会检查拼写。但我的想法是使用拒绝事件获取记录的最新id,并对表的其余部分进行操作。要优化查询,可以将此id存储在变量中
SELECT user, COUNT(event = 'sign') AS `num_of_signed_docs`
FROM audittable
WHERE `id` > (SELECT `id` FROM audittable
WHERE `event` = 'reject'
ORDER BY `id` DESC LIMIT 1)
GROUP BY user;
您可以为每一行创建一个名为type的虚拟列,并应用所需的条件,该列的值为0或1,并对其求和:
select t.username, sum(t.type) num_of_signed_docs from (
select a.username,
case
when event = 'reject' then 0
when exists
(select 1 from audit where doc_id = a.doc_id and
datetime > a.datetime and event = 'reject')
then 0
else 1 end as type
from audit a
) t
group by t.username
请参阅有关SQL Server的详细信息
而MySQL的
编辑
请参阅有关SQL Server的详细信息
MySQL的表:更新了3-这是不是把它们放在一起了
Create Table signed
(
id Int,
doc_id Int,
dt Datetime,
usr VarChar(25),
event VarChar(25)
)
Insert Into signed Values
(1,10,'2018/03/04','john','sign'),
(2,10,'2018/03/05','anna','sign'),
(3,10,'2018/03/11','paul','reject'),
(4,10,'2018/03/23','marc','sign'),
(5,11,'2018/03/23','john','sign'),
(6,10,'2018/03/24','luke','create'),
(7,11,'2018/03/24','john','sign')
TSQL:
if Not Exists
(Select Top 1 dt From signed Where event = 'reject')
With cte1 As
(Select id as rid,doc_id,usr, count(*) As numb From signed
Where event = 'sign'
Group by id,doc_id,usr
), cte2 As
( Select distinct usr, doc_id From cte1 )
Select usr, Count(doc_id) As num From cte2
Group By usr
Else
With cte3 As
(
Select id, doc_id, usr, count(*) As numb From signed
Where dt > (Select Top 1 dt From signed Where event = 'reject') And event = 'sign'
Group by id,doc_id,usr
), cte4 As
( Select distinct usr, doc_id From cte3 )
Select usr, Count(doc_id) As num From cte4
Group By usr
结果:
usr numb
john 1
marc 1
因为您标记了MySQL和SQL server MSSQL,或者您需要有效的ANSI SQL跨数据库查询,所以使用哪种SQL方言?我主要需要SQL server的查询,但在MySQL中也是OK的。此查询将给出anna | 1而不是anna | 0。。Paul拒绝了Anna的签名活动,因为doc_id=10。至少我是这样理解他的问题的。这不起作用,你不能用“拒绝事件”计算所有记录的最新id的文档,因为一个文档的拒绝不应该影响另一个文档的用户数。@trokiize它不计算“拒绝事件”但在上次拒绝之后的记录!看见它使用括号中的reject select语句获取最后一条记录的编号,然后在id>select…之后对记录进行计数。。。。所有这些记录都将被签署,而不是rejected@trokiize对于您的示例,请选择id。。。限制1将返回3。将使用此编号:在主select语句中只考虑id>3的记录,但返回的编号不适合此问题,因为您的编号基于上次拒绝,但此表包含n个文档,因此,每个文档都在不同的id上有其最后一次拒绝。您的方法只检查最后一次拒绝,并且忽略拒绝之前的所有文档,这不是我想要的。当所有文档都签名后,它将为所有文档返回0users@trokiize我完全忽略了你努力的明显部分。请看我的更新。我添加了检查,以查看是否没有拒绝,然后针对该条件执行标准的group by语句。我再次测试了它,似乎并不是在所有情况下都有效。我还更新了我的帖子,看一看。@trokiize我已经应用了一个新的修订版来解释其他事件,如“创建”。我相信我在24分钟前用'distinct'-level3looper提高了关注度。这一次,如果一个用户签署了相同的文档4次,结果是1,这是好的,但是如果一个用户签署了4个不同的文档,结果又是1,这是不好的。我已经更新了我的帖子。对于最初的问题,你的回答很接近。你能再解决一下吗?当一个用户在同一份文件上签了三次名时,应该只算一次,因为你的答案似乎涵盖了所有情况。谢谢
Create Table signed
(
id Int,
doc_id Int,
dt Datetime,
usr VarChar(25),
event VarChar(25)
)
Insert Into signed Values
(1,10,'2018/03/04','john','sign'),
(2,10,'2018/03/05','anna','sign'),
(3,10,'2018/03/11','paul','reject'),
(4,10,'2018/03/23','marc','sign'),
(5,11,'2018/03/23','john','sign'),
(6,10,'2018/03/24','luke','create'),
(7,11,'2018/03/24','john','sign')
if Not Exists
(Select Top 1 dt From signed Where event = 'reject')
With cte1 As
(Select id as rid,doc_id,usr, count(*) As numb From signed
Where event = 'sign'
Group by id,doc_id,usr
), cte2 As
( Select distinct usr, doc_id From cte1 )
Select usr, Count(doc_id) As num From cte2
Group By usr
Else
With cte3 As
(
Select id, doc_id, usr, count(*) As numb From signed
Where dt > (Select Top 1 dt From signed Where event = 'reject') And event = 'sign'
Group by id,doc_id,usr
), cte4 As
( Select distinct usr, doc_id From cte3 )
Select usr, Count(doc_id) As num From cte4
Group By usr
usr numb
john 1
marc 1