我正在使用 SQL Server 2016
并有一个包含以下数据的表:
PlaySeq | TransMaxValue |
---|---|
1 | 250 |
2 | 500 |
3 | 0 |
4 | 400 |
5 | 0 |
6 | 300 |
7 | 500 |
8 | 0 |
9 | 0 |
我正在尝试构建一个向该数据集添加列 TransMaxValueContd
的查询。
该 TransMaxValueContd
列应保留在列 TransMaxValue
中遇到的最后一个非零值。
订购由PlaySeq
完成。
我预期的查询结果如下:
PlaySeq | TransMaxValue | TransMaxValueContd |
---|---|---|
1 | 250 | 250 |
2 | 500 | 500 |
3 | 0 | 500 |
4 | 400 | 400 |
5 | 0 | 400 |
6 | 300 | 300 |
7 | 500 | 500 |
8 | 0 | 500 |
9 | 0 | 500 |
我一直在使用像 LAST_VALUE()
和 LAG()
这样的窗口函数,但似乎无法得到正确的结果。
也许我把它复杂化了。
有人知道怎么做吗?
ps:我只是在寻找查询。无需修改源表。
编辑:添加了一个尝试失败的 SQLFiddle example,即:
SELECT a.PlaySeq,
a.TransMaxValue,
IIF(ISNULL(LAG(a.TransMaxValue,1) OVER (ORDER BY a.PlaySeq), a.TransMaxValue) = a.TransMaxValue, a.TransMaxValue, LAG(a.TransMaxValue,1) OVER (ORDER BY a.PlaySeq)) AS TransMaxValueContd
FROM myTable AS a;
编辑:感谢您的所有回答,提供了新的有用见解!
我最终使用了这个,灵感来自 answer 的 SteveC。
SELECT a.PlaySeq,
a.TransMaxValue,
(SELECT TOP 1 x.TransMaxValue
FROM myTable AS x
WHERE x.PlaySeq <= a.PlaySeq
AND x.TransMaxValue != 0
ORDER BY x.PlaySeq DESC) AS TransMaxValueContd
FROM myTable AS a;
答案 0 :(得分:2)
一种简单的方法是使用 OUTER APPLY
和 SELECT TOP(1)
。像这样
select m.PlaySeq, m.[TransMaxValue],
case when m.[TransMaxValue]=0
then oa.TransMaxValue
else m.TransMaxValue end TransMaxValueContd
from myTable m
outer apply (select top(1) mm.[TransMaxValue]
from myTable mm
where m.PlaySeq>mm.PlaySeq
and mm.[TransMaxValue]>0
order by mm.PlaySeq desc) oa;
PlaySeq TransMaxValue TransMaxValueContd
1 250 250
2 500 500
3 0 500
4 400 400
5 0 400
6 300 300
7 500 500
8 0 500
9 0 500
答案 1 :(得分:1)
也许这会有所帮助:
DECLARE @Tab TABLE(PlaySeq INT, TransMaxValue INT)
INSERT @Tab
VALUES(1,250),(2,500),(3,0),(4,400),(5,0)
,(6,300),(7,500),(8,0),(9,0)
SELECT PlaySeq,
TransMaxValue,
FIRST_VALUE(TransMaxValue) OVER(PARTITION BY Grp ORDER BY PlaySeq) AS TransMaxValueContd
FROM (
SELECT
PlaySeq,
TransMaxValue,
SUM(CASE WHEN TransMaxValue = 0 THEN 0 ELSE 1 END) OVER(ORDER BY PlaySeq) AS Grp
FROM @Tab
) AS tbl
ORDER BY PlaySeq
答案 2 :(得分:0)
请尝试以下解决方案。
基于Windows函数ROW_NUMBER()
和非等关系子句:
FROM @tbl AS t1 INNER JOIN
@tbl AS t2 ON t1.PlaySeq > t2.PlaySeq
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (PlaySeq INT, TransMaxValue INT);
INSERT INTO @tbl (PlaySeq, TransMaxValue) VALUES
(1, 250),
(2, 500),
(3, 0 ),
(4, 400),
(5, 0 ),
(6, 300),
(7, 500),
(8, 0 ),
(9, 0 );
-- DDL and sample data population, end
;WITH rs AS
(
SELECT t1.*
, t2.TransMaxValue AS prev_value
, ROW_NUMBER() OVER (PARTITION BY t1.PlaySeq ORDER BY t2.PlaySeq DESC) AS seq
FROM @tbl AS t1 INNER JOIN
@tbl AS t2 ON t1.PlaySeq > t2.PlaySeq
WHERE t2.TransMaxValue > 0
)
SELECT PlaySeq, TransMaxValue, TransMaxValue AS TransMaxValueContd
FROM @tbl WHERE PlaySeq = 1
UNION ALL
SELECT PlaySeq, TransMaxValue, IIF(TransMaxValue > 0, TransMaxValue, prev_value) AS TransMaxValueContd
FROM rs
WHERE seq = 1
ORDER BY PlaySeq ASC;
输出
+---------+---------------+--------------------+
| PlaySeq | TransMaxValue | TransMaxValueContd |
+---------+---------------+--------------------+
| 1 | 250 | 250 |
| 2 | 500 | 500 |
| 3 | 0 | 500 |
| 4 | 400 | 400 |
| 5 | 0 | 400 |
| 6 | 300 | 300 |
| 7 | 500 | 500 |
| 8 | 0 | 500 |
| 9 | 0 | 500 |
+---------+---------------+--------------------+
答案 3 :(得分:0)
可能有更好的方法,但您可以尝试使用相关子查询:
SELECT q.PlaySeq, q.TransMaxValue
, (CASE
WHEN q.TransMaxValue <> 0 THEN q.TransMaxValue
ELSE (SELECT d.TransMaxValue FROM myTable d WHERE d.PlaySeq = q.PlaySeqRef)
END) TransMaxValueContd
FROM (
SELECT PlaySeq
, TransMaxValue
, (SELECT MAX(PlaySeq)
FROM myTable b
WHERE b.PlaySeq < a.PlaySeq
AND b.TransMaxValue <> 0) PlaySeqRef
FROM myTable a) q;