我目前正在用 SQL 编写代码,将红色列添加到下表中:
逻辑如下:
对于每一行:
如果该行的标志=1,则使用该行的日期
如果该行的标志=0,则找到同一方标志=1的最新行(基于日期),并返回该行的日期。如果不存在这样的行,则返回 null
我找到了一种通过将表格连接到自身来实现此目的的方法,但我想避免这样做,因为表格的大小非常大。
我有什么
select b.*, a.date,
from table a left join table b on a.party=b.party
where a.flag =1
有人告诉我我可以使用滞后函数、分区函数以及何时返回我想要的值的情况,但我一直无法弄清楚。
有人可以帮忙吗?非常感谢!
试试这个
DECLARE @tab1 TABLE(PARTY CHAR(1),DATE DATE,Flag bit)
INSERT INTO @tab1
SELECT 'A','7-24-2018',1 Union ALL
SELECT 'A','7-28-2018',0 Union ALL
SELECT 'A','7-29-2018',0 Union ALL
SELECT 'A','7-29-2018',0 Union ALL
SELECT 'B','7-13-2018',1 Union ALL
SELECT 'B','7-17-2018',0 Union ALL
SELECT 'B','7-18-2018',0 Union ALL
SELECT 'C','7-8-2018',1 Union ALL
SELECT 'C','7-13-2018',0 Union ALL
SELECT 'C','7-19-2018',0 Union ALL
SELECT 'C','7-19-2018',0 Union ALL
SELECT 'C','7-20-2018',0
select t.*,
max(case when flag = 1 then date end) over (partition by PARTY order by date) as [Last Flag On Date]
from @tab1 t
使用
CROSS APPLY()
获取标志为 1 的最新行
SELECT *
FROM yourtable t
CROSS APPLY
(
SELECT TOP 1 x.Date as [Last flag on date]
FROM yourtable x
WHERE x.Party = t.Party
AND x.Flag = 1
ORDER BY x.Date desc
) d
是的,如果写得正确,可以通过连接表来完成。
@Sahi 查询也很好,很简单。
既然你要求
Dynamic LAG()
这个查询的性能可能很高,也可能不是很高,但它确实值得学习。
使用各种示例数据对此进行测试,并告诉我它不适用于哪种场景。 这样我就可以相应地修改我的脚本。
DECLARE @tab1 TABLE(PARTY CHAR(1),DATE DATE,Flag bit)
INSERT INTO @tab1
SELECT 'A','7-24-2018',1 Union ALL
SELECT 'A','7-28-2018',0 Union ALL
SELECT 'A','7-29-2018',0 Union ALL
SELECT 'A','7-29-2018',0 Union ALL
SELECT 'B','7-13-2018',1 Union ALL
SELECT 'B','7-17-2018',0 Union ALL
SELECT 'B','7-18-2018',0 Union ALL
SELECT 'C','7-8-2018',1 Union ALL
SELECT 'C','7-13-2018',0 Union ALL
SELECT 'C','7-19-2018',0 Union ALL
SELECT 'C','7-19-2018',0 Union ALL
SELECT 'C','7-20-2018',0;
WITH cte
AS (SELECT *,
Row_number()
OVER (
partition BY party
ORDER BY flag DESC, [date] DESC ) rn
FROM @tab1)
SELECT *,
CASE
WHEN flag = 1 THEN [date]
ELSE Lag([date], (SELECT TOP 1 a.rn - a1.rn
FROM cte a1
WHERE a1.party = a.party))
OVER (
ORDER BY party )
END
FROM cte a
试试这个:->
select
b.*,
a.date,
from
table a
left join table b on a.party = b.party
where
a.flag = CASE WHEN a.flag = 1 THEN a.date WHEN a.flag = 0 THEN (
SELECT
date
FROM
(
SELECT
TOP 1 row_number() OVER (
ORDER BY
a.date DESC
) rs,
a.date
FROM
a
WHERE
a.flag = 1
GROUP BY
a.date
) s
) END