在一个结果集中计算2个不同的列

时间:2018-12-03 19:48:00

标签: sql sql-server count

我遇到问题并得到不正确的结果。我想统计每年有休假日期和死亡日期的记录,并将它们显示在一张表中。

这是我到目前为止的查询:

select  year(leavedate) as leave_year,  count(year(leavedate)) as cnt_leave ,  count(year(DeceasedDate)) as cnt_dod 
from clients
where leavedate is not null and DeceasedDate is not null 
group by year(leavedate),year(DeceasedDate)
order by 1 desc

这是我想要的目标:

+------+-----------+---------+
| Year | Cnt_leave | Cnt_dod |
+------+-----------+---------+
| 2018 |       542 |    5685 |
| 2017 |      8744 |    5622 |
| 2016 |       556 |     325 |
| etc  |           |         |
+------+-----------+---------+

我应该在两个单独的select语句中执行还是可以在一个语句中执行? 感谢您的反馈!

5 个答案:

答案 0 :(得分:1)

我会做的:

with
l as (
  select year(leavedate) as y, count(*) as c
  from clients 
  group by year(leavedate)
),
d as (
  select year(deceaseddate) as y, count(*) as c
  from clients 
  group by year(deceaseddate)
)
select
  coalesce(l.y, d.y) as year,
  coalesce(l.c, 0) as cnt_leave,
  coalesce(d.c, 0) as cnt_dod
from l
full outer join d on l.y = d.y
order by coalesce(l.y, d.y) desc

答案 1 :(得分:0)

如果我理解,您正在寻找这样的东西:

select year(leavedate) as leave_year,  sum(case leavedate when null then 0 else 1 end) as cnt_leave, 
sum(case DeceasedDate when null then 0 else 1 end) as cnt_dod 
from clients
where leavedate is not null or DeceasedDate is not null 
group by year(leavedate)
order by 1 desc

答案 2 :(得分:0)

您需要分两步计算,因为Year(LeaveDate)Year(DeceasedDate)无关;但是您可以通过一些CTE构造来组合这些SELECT。

实际上,有(至少)两种方法可以做到这一点,不确定哪种方法会表现更好;您需要尝试找出最适合您数据的方法。

SELECT client_id = 1, LeaveDate = Convert(datetime, '20080118'), DeceasedDate = Convert(datetime, '20090323')
  INTO #test
 UNION ALL SELECT client_id = 2, LeaveDate = '20100118', DeceasedDate = '20100323'
 UNION ALL SELECT client_id = 3, LeaveDate = '20100118', DeceasedDate = '20120323'

;WITH src 
   AS (SELECT * 
         FROM #test 
        WHERE LeaveDate IS NOT NULL 
          AND DeceasedDate IS NOT NULL),    
      leave
   AS (SELECT yr = Year(LeaveDate), cnt = COUNT(*) FROM src GROUP BY Year(LeaveDate)),
      deceased
   AS (SELECT yr = Year(DeceasedDate), cnt = COUNT(*) FROM src GROUP BY Year(DeceasedDate))

SELECT yr              = ISNULL(l.yr, d.yr),
       cntLeaveDate    = ISNULL(l.cnt, 0),
       cntDeceasedDate = ISNULL(d.cnt, 0)
  FROM leave l
  FULL OUTER JOIN deceased d
               ON d.yr = l.yr
 ORDER BY 1 DESC

;WITH src 
   AS (SELECT * 
         FROM #test 
        WHERE LeaveDate IS NOT NULL 
          AND DeceasedDate IS NOT NULL),    
      years
   AS (SELECT DISTINCT yr = Year(LeaveDate) FROM src
        UNION -- Do not UNION ALL here, you want to avoid doubles!
       SELECT DISTINCT yr = Year(DeceasedDate) FROM src)

SELECT yr,
       cntLeaveDate    = SUM ( CASE WHEN Year(LeaveDate)    = yr THEN 1 ELSE 0 END),
       cntDeceasedDate = SUM ( CASE WHEN Year(DeceasedDate) = yr THEN 1 ELSE 0 END)
  FROM years, #test
 WHERE LeaveDate IS NOT NULL 
   AND DeceasedDate IS NOT NULL 
 GROUP BY yr
  ORDER BY 1 DESC

  DROP TABLE #test

答案 3 :(得分:0)

我会为此使用apply。 。 。我认为这是最简单的解决方案:

select  year(dte) as year,  sum(isleave) as num_leaves, sum(isdeceased) as numdeceased
from clients c cross apply
     (values (leavedate, 1, 0),
             (deceaseddate, 0, 1)
     ) v(dte, isleave, isdeceased)
where dte is not null 
group by year(dte)
order by 1 desc;

答案 4 :(得分:-1)

SQL FIDDLE

根据您的评论,您所需要做的就是删除where子句并限制分组依据。

select  
    year(leavedate) as leave_year,
     count(year(leavedate)) as cnt_leave ,  
     count(year(DeceasedDate)) as cnt_dod 
from clients
--where leavedate is not null and DeceasedDate is not null 
group by year(leavedate) --,year(DeceasedDate)
--order by 1 desc

或者,如果您的数据在任一列中都可以有NULL,我在上面假设,因此省略了您想要的where子句:

select  
    coalesce(year(leavedate),year(DeceasedDate)) as the_year,
     count(year(leavedate)) as cnt_leave ,  
     count(year(DeceasedDate)) as cnt_dod 
from clients
--where leavedate is not null and DeceasedDate is not null 
group by coalesce(year(leavedate),year(DeceasedDate))
--order by 1 desc

这里是例子:

declare @clients table (leavedate date null, DeceasedDate date null)
insert into @clients
values
('20180101',NULL)
,(null,'20170101')
,('20150101','20150101')

select  
    year(leavedate) as leave_year,
     count(year(leavedate)) as cnt_leave ,  
     count(year(DeceasedDate)) as cnt_dod 
from @clients
--where leavedate is not null and DeceasedDate is not null 
group by year(leavedate) --,year(DeceasedDate)
--order by 1 desc


select  
    coalesce(year(leavedate),year(DeceasedDate)) as the_year,
     count(year(leavedate)) as cnt_leave ,  
     count(year(DeceasedDate)) as cnt_dod 
from @clients
--where leavedate is not null and DeceasedDate is not null 
group by coalesce(year(leavedate),year(DeceasedDate))
--order by 1 desc