根据条件从表中选择计数

时间:2019-01-16 18:46:49

标签: mysql sql sql-server

我有一个这样的审核表:

id  doc_id  datetime      user   event
---|------|------------|--------|--------
1  | 10   | 04/03/2018 | john   | sign 
2  | 10   | 05/03/2018 | anna   | sign
3  | 10   | 11/03/2018 | paul   | reject
4  | 10   | 23/03/2018 | marc   | sign
5  | 11   | 23/03/2018 | john   | sign
6  | 11   | 24/03/2018 | luke   | create
7  | 11   | 24/03/2018 | john   | sign

我需要获取用户及其签名文件的数量。用户可以签名文档n次,但计数时用户已经签名1次。如果在一个文档上调用了拒绝,则该文档不会考虑所有用户先前的拒绝。此外,查询性能也非常重要,因为有数百万个条目。

结果将是:

user   num_of_signed_docs
-----|-------------------|
john |  1                |  
marc |  1                |

4 个答案:

答案 0 :(得分:1)

您为每一行创建一个虚拟列,名为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,请参见demo
demo for MySQL

编辑

select a.username, count(distinct a.doc_id) num_of_signed_docs 
from audit a
where
  a.event = 'sign'
  and
  not exists (
    select 1 from audit where 
      doc_id = a.doc_id and datetime > a.datetime and event = 'reject'    
  )
group by a.username

有关SQL Server,请参见demo
demo for MySQL

答案 1 :(得分:0)

这是您想要的吗?

select user, sum(case when event = 'sign' then 1 else 0 end) as num_signs
from audittable
group by user;

答案 2 :(得分:0)

对不起,如果有错别字。我无法检查拼写。但是我的想法是获取带有拒绝事件的最新记录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;

答案 3 :(得分:0)

表:更新#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