我有一个需要报告房屋状况的系统。如果房子没有通过主要的房屋标准,房子将无法通过住房标准。元素或积累2个次要元素时。这是一个可以粘贴到管理工作室并运行的示例 - 使用注释来解释我想要实现的目标:
WITH T1 AS
( SELECT
1 propertyid,
'Principal roof covering' text,
0 isprimary,
CAST('1 Apr 2016' AS datetime) date,
'This should not appear because it is secondary and
there are no subsequent secondary elements for this property' comment
UNION SELECT
1,
'Chimney stacks',
0,
CAST('1 Apr 2015' AS datetime),
'This should appear unadjusted because it is secondary and there is a
preceding secondary element for the same property' UNION SELECT
1,
'Bathroom condition',
1,
CAST('1 Apr 2014' AS datetime),
'This should appear unadjusted because it is primary' UNION SELECT
2,
'Damp proof course',
0,
CAST('1 Apr 2016' AS datetime),
'This should not appear because it is secondary and there are no
subsequent secondary elements for this property'
UNION SELECT
1,
'External wall finish',
0,
CAST('1 Apr 2014' AS datetime),
'This should get it''s date adjusted to 2015 because it is secondary
and the next secondary element is in 2015' UNION SELECT
1,
'Flashings',
0,
CAST('1 Jun 2015' AS datetime),
'This should get it''s date adjusted to Sep 2015 because it is secondary
and the next secondary element is in Sep 2015' UNION SELECT
1,
'Underground drainage',
0,
CAST('1 Sep 2015' AS datetime),
'This should appear unadjusted because it is secondary and there is a
preceding secondary element for the same property'
)
SELECT
*
FROM t1
ORDER BY date
如何过滤掉不具有后续辅助元素的辅助元素,并调整后续元素作为后续元素日期的元素的日期?
答案 0 :(得分:1)
请看这个:
SELECT t1.*
,CASE
WHEN (t1.isprimary = 1)
OR (
t1.isprimary = 0
AND Post.DATE IS NULL
)
THEN T1.DATE
ELSE Post.DATE
END AS Date_Corrected
FROM t1
CROSS APPLY (
SELECT TOP (1) t2.DATE
FROM T1 t2
WHERE T2.propertyid = t1.propertyid
AND t2.DATE > t1.DATE
AND t2.isprimary = 0
ORDER BY t2.date
) Post
OUTER APPLY (
SELECT TOP (1) t2.DATE
FROM T1 t2
WHERE T2.propertyid = t1.propertyid
AND t2.DATE < t1.DATE
AND t2.isprimary = 0
order by t2.date DESC
) Pres
ORDER BY t1.DATE
答案 1 :(得分:1)
以下查询应返回您想要的内容:
WITH T1 AS
(
SELECT *
, ROW_NUMBER() OVER (PARTITION BY propertyid, isprimary ORDER BY date) AS PropNo
, COUNT(*) OVER (PARTITION BY propertyid, isprimary) AS PropCount
FROM
-- Replace below with your source data table
(VALUES(1,'Bathroom condition',1,'2014-04-01')
,(1,'External wall finish',0,'2014-04-01')
,(1,'Chimney stacks',0,'2015-04-01')
,(1,'Principal roof covering',0,'2016-04-01')
,(2,'Damp proof course',0,'2016-04-01')) T(propertyid, text, isprimary, date)
)
SELECT
T1.propertyid
, T1.text
, T1.isprimary
, CASE
WHEN T1.isprimary = 1 OR T1.PropNo = T1.PropCount - 1 THEN T1.date
ELSE ISNULL(T1Next.date, T1.date) END AS [date]
FROM T1
LEFT JOIN T1 AS T1Next ON T1.propertyid = T1Next.propertyid
AND T1.isprimary = T1Next.isprimary
AND T1.PropNo = T1Next.PropNo - 1
WHERE T1.isprimary = 1
OR (T1.PropNo < T1.PropCount)
我使用ROW_NUMBER()和COUNT(*)函数来确定何时有后续行。要应用后续行中的日期,我使用LEFT JOIN。
修改强> 将左连接更改为此连接可确保连接仅在辅助元素上发生,并且仅在每个第二个元素上发生:
LEFT JOIN T1 AS T1Next ON T1.propertyid = T1Next.propertyid
AND T1.isprimary = 0
AND T1Next.isprimary = 0
AND T1.PropNo = T1Next.PropNo - 1
AND T1Next.PropNo % 2 = 0
这意味着我们不需要案例陈述,只需这样:
ISNULL(T1Next.date, T1.date) AS [date]
但是where声明并不完全正确。这有效:
WHERE T1.isprimary = 1
OR (T1.PropNo % 2 = 0) --every 2nd one
OR T1Next.date IS NOT NULL --and the 1st if there is a 2nd