SQL 到 return 每行 1 列范围在 2017 年或 2018 年或 2019 年
SQL to return 1 for each row with column range in 2017 or 2018 or 2019
我有一个如下所示的查询:
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]
不过这似乎不起作用。参见上面table中的2018年专栏。它显示所有返回的 1,并且不排除空值。这很复杂。 status_from 和 status_thru 可能与 2018 一起下降,或者 2018 可能在 status_from 和 status_thru 内,它们应该都是 1.
如何排除空值,以及如何在状态日期包括 2018 年时显示 1?
我看过 range within range, and return 0 or 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]
but I'm getting Ambiguous column name 'status_from_date'. Ambiguous
column name 'status_thru_date'. Only one expression can be specified
in the select list when the subquery is not introduced with 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]--------
对于以下数据:status_from:2014-10-01 和 status_to:2016-09-30
你可以这样做:
while 将检查开始或结束是否包含 2018 年,或者日期是否在开始和结束之间
CREATE TABLE #testTable (
Status_from_date DATETIME,
Status_thru_date DATETIME
)
INSERT INTO #testTable (
Status_from_date,
Status_thru_date
)
VALUES (
'2017-06-01 00:00',
'2019-05-31 00:00'
),
(
NULL,
'2010-01-28 07:38'
),
(
'2018-07-01 00:00',
'2020-06-30 00:00'
)
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'
FROM #testTable
DROP TABLE #testTable
产生:
Status_from_date Status_thru_date 2018
2017-06-01 00:00:00.000 2019-05-31 00:00:00.000 1
NULL 2010-01-28 07:38:00.000 0
2018-07-01 00:00:00.000 2020-06-30 00:00:00.000 1
如果你想在 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
我有一个如下所示的查询:
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]
不过这似乎不起作用。参见上面table中的2018年专栏。它显示所有返回的 1,并且不排除空值。这很复杂。 status_from 和 status_thru 可能与 2018 一起下降,或者 2018 可能在 status_from 和 status_thru 内,它们应该都是 1.
如何排除空值,以及如何在状态日期包括 2018 年时显示 1?
我看过 range within range, and return 0 or 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]
but I'm getting Ambiguous column name 'status_from_date'. Ambiguous column name 'status_thru_date'. Only one expression can be specified in the select list when the subquery is not introduced with 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]--------
对于以下数据:status_from:2014-10-01 和 status_to:2016-09-30
你可以这样做:
while 将检查开始或结束是否包含 2018 年,或者日期是否在开始和结束之间
CREATE TABLE #testTable (
Status_from_date DATETIME,
Status_thru_date DATETIME
)
INSERT INTO #testTable (
Status_from_date,
Status_thru_date
)
VALUES (
'2017-06-01 00:00',
'2019-05-31 00:00'
),
(
NULL,
'2010-01-28 07:38'
),
(
'2018-07-01 00:00',
'2020-06-30 00:00'
)
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'
FROM #testTable
DROP TABLE #testTable
产生:
Status_from_date Status_thru_date 2018
2017-06-01 00:00:00.000 2019-05-31 00:00:00.000 1
NULL 2010-01-28 07:38:00.000 0
2018-07-01 00:00:00.000 2020-06-30 00:00:00.000 1
如果你想在 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