首页 > 解决方案 > SQL 为 2017 年或 2018 年或 2019 年的列范围内的每一行返回 1

问题描述

我有一个看起来像这样的查询:

SELECT DISTINCT
     p.person_ID
     ,p.Last_Name 
     ,ISNULL(p.Middle_Initial, '') AS Middle
     ,p.First_Name
     ,sh.Status_from_date
     ,sh.Status_thru_date
     --(a)
FROM 
    person p
INNER JOIN 
    Person_Facilities f ON p.Person_ID = f.Person_ID
LEFT OUTER JOIN
    rv_person_status_hist sh ON p.person_ID = sh.person_ID
ORDER BY 
    Last_Name

返回的数据看起来像这样的东西(暂时忽略 2018 列):

Person_id  Last_Name  Middle  First_Name  Status_from_date Status_thru_date    2018
8000       Skywalker  Dude    Luke        Null             2010-01-28 07:38      1
9000       Yoda               Phinnius    2017-06-01 00:00 2019-05-31 00:00      1
1000       Lamb       Little  Mary        2018-07-01 00:00 2020-06-30 00:00      1
2000       Spider     Bitsy   Itsy        2016-11-01 00:00 2017-06-30 00:00      1

如何添加一列,比如 [2018],如果 status_from_date 到 status_thru_date 在 2018 年,则为 1,否则为 0?

我想在查询的 --(a) 中添加以下内容:

,(SELECT case 
             when exists
             (
                select *  --
                FROM   dbo.RV_Person_status_hist
                where 
                status_from_date is not null
                and
                ('1-1-2018' between status_from_date and status_thru_date)
                and status_from_date is not null
                ) 
                then 1 else 0 end  ) 

                  AS [2018]

不过,这似乎不起作用。请参阅上表中的 2018 年列。它显示所有返回的 1,并且不排除空值。这很复杂。status_from 和 status_thru 可能与 2018 一起下降,或者 2018 可能在 status_from 和 status_thru 中,它们都应该是 1。

如何排除空值,当状态日期包括 2018 年时如何显示 1?

我查看了range 内的 range,并返回 0 或 1。我不认为我有所有案例,因为范围也重叠。

**更新:我尝试在上面的 --(a) 中添加它,根据下面的潜在答案:

,(SELECT status_from_date, status_thru_date,
             case 
             when datepart(year, status_from_date)='2018'
               or datepart(year, status_thru_date)='2018'
               or (
                status_from_date <= '01/01/2018'
                and status_thru_date >= '12/12/2018'
               )
            then 1
              else 0
              end)  AS [2018]

但我得到了模棱两可的列名'status_from_date'。不明确的列名“status_thru_date”。当不使用 EXISTS 引入子查询时,选择列表中只能指定一个表达式。

有任何想法吗?弄清楚了。

**更新2:这个怎么样?

,(case when (
                (
                    (sh.status_from_date is null or sh.status_from_date <= '2017-01-01') and
                    (sh.status_thru_date is null or sh.status_thru_date >= '2017-12-31')
                ) 
                or
                (
                    (f.status_from_date is null or f.status_from_date <= '2017-01-01') and
                    (f.status_thru_date is null or f.status_thru_date >= '2017-12-31')
                ) 
                or
                (
                    (datepart(year, sh.status_from_date)='2017') or
                    (datepart(year, sh.status_thru_date)='2017') or
                    (datepart(year, f.status_from_date)='2017') or
                    (datepart(year, f.status_from_date)='2017')

                ) 
                and
                    p.Sex='M'
            )
       then 1 else 0
end) as [2017_Male]
,(case when (
                (
                    (sh.status_from_date is null or sh.status_from_date <= '2017-01-01') and
                    (sh.status_thru_date is null or sh.status_thru_date >= '2017-12-31')
                ) 
                or
                (
                    (f.status_from_date is null or f.status_from_date <= '2017-01-01') and
                    (f.status_thru_date is null or f.status_thru_date >= '2017-12-31')
                ) 
                or
                (
                    (datepart(year, sh.status_from_date)='2017') or
                    (datepart(year, sh.status_thru_date)='2017') or
                    (datepart(year, f.status_from_date)='2017') or
                    (datepart(year, f.status_from_date)='2017')

                ) 
                and
                    p.Sex='F'
            )
       then 1 else 0
end) as [2017_Female]--------

那个在 2017 年男性和女性列中为以下数据输入 1:status_from: 2014-10-01 和 status_to: 2016-09-30

标签: sqldatesql-server-2008-r2range

解决方案


如果你想在 2018 年有任何重叠,那么:

(case when (status_from_date is null or status_from_date < '2019-01-01') and
           (status_to_date is null or status_to_date >= '2018-01-01')
      then 1 else 0
 end) as is_2018

如果您想要全年的重叠:

(case when (status_from_date is null or status_from_date <= '2018-01-01') and
           (status_to_date is null or status_to_date >= '2018-12-31')
      then 1 else 0
 end) as is_2018

推荐阅读