在同一个表的计数中包含零

时间:2016-06-20 19:19:42

标签: sql sql-server tsql

我有两列的表,一个是int,另一个是varchar列

SeqId   status
int     varchar(50)

状态栏有10个状态,例如status1,status2,status3,... status10

我想写一个查询来查找SeqId的范围,其中status7,status8,status9 count(*)为零。

表数据,

SeqId   Status
 1   status1
 2   status2
 3   status3
 4   status4
 5   status5
 6   status6
 7   status7
 8   status8
 9   status9
 10  status10
 11  status1
 12   status2
 13   status3
 14   status4
 15   status5
 16   status9
 17   status2
 18   status7
 19   status3
 20   status5
 ......
 1000 status6 

我的第一个期望输出

当我使用15到20之间的范围时,

不正确的查询现在不包含零,

 Select status, count(*) 
 from table1 
 where seqId between 15 and 20 
 group by status
**Status      Count**
 status1       0
 status2       1
 status3       1
 status4       0
 status5       2
 status6       0
 status7       1
 status8       0
 status9       1
 status10      0

接下来如果可能的话,我想找到一个范围,其中所有这3种状态,8,9和10都为零。

5 个答案:

答案 0 :(得分:2)

您可以使用case语句将其转换为布尔问题。所以:

select t.*, (case when status in ('status8', 'status9', 'status10') then 0 else 1 end) as flag
from t;

您现在想要找到最长的零序列。这是一个间隙和岛屿问题。一种解决方案是行号的差异以定义组:

select top 1 min(id), max(id), count(*) as length
from (select t.*, 
             (row_number() over (order by id) - row_number() over (partition by flag order by id)) as grp
      from (select t.*, (case when status in ('status8', 'status9', 'status10') then 0 else 1 end) as flag
            from t
           ) t
     ) t
where flag = 0
group by grp, flag
order by count(*) desc;

答案 1 :(得分:0)

假设您有一个状态表:

SELECT A.STATUS, COALESCE(B.COUNT, 0) AS COUNT FROM STATUS_TABLE A
LEFT JOIN (SELECT STATUS, COUNT(*) AS COUNT FROM TABLE1 GROUP BY STATUS) B
ON A.STATUS = B.STATUS

答案 2 :(得分:0)

Select base.status, count(statusVal.Status) 
from table1 base 
left join ( select distinct Status from table1 
          ) statusVal 
       on statusVal.Status = base.status
where seqId between 15 and 20 
group by base.status

全部为零

select SeqId from data 
except 
select SeqId from data where Status in ( ..... )

答案 3 :(得分:0)

对于您的第一个问题,通用的t-sql解决方案将是

create table #t (id int, [status] varchar(12))
go
insert into #t (id, status) values
  (1   ,'status1')
 , (2   ,'status2')
 , (3   ,'status3')
 , (4   ,'status4')
 , (5   ,'status5')
 , (6   ,'status6')
 , (7   ,'status7')
 , (8   ,'status8')
 , (9   ,'status9')
 , (10  ,'status10')
 , (11  ,'status1')
 , (12   ,'status2')
 , (13   ,'status3')
 , (14   ,'status4')
 , (15   ,'status5')
 , (16   ,'status9')
 , (17   ,'status2')
 , (18   ,'status7')
 , (19   ,'status3')
 , (20   ,'status5')
 go

; WITH c (status, cnt) as
(
  select distinct [status], cnt=0 
  from #t
) 
, c2 as ( select t.[status], cnt=count(*)
 from #t t
 where t.id between 15 and 20
 group by t.[Status])
 select c.* from c2 
 right join c 
 on c.[status]=c2.[status]
 where c2.status is null
 union
select c2.* from c2;

对于你的第二个问题,@ Gordon Linoff提供了一个很好的解决方案,但我认为他的解决方案中存在一个错字。 where子句应该是

where flag = 1 -- instead of 0

答案 4 :(得分:0)

select convert(int,substring(a.[status],7,2)),a.*,isnull(b.CNT,0)
from
    (select distinct [status] from #t) a
left join
    (select [status],COUNT(*)as CNT from #t
     where id between 15 and 20
     Group by [status]) b
on a.status=b.status
order by 1