我需要从SQL中的一个表中获取结果列表,以便我需要在where语句选择的日期之前紧跟其日期值的行。在下图中,我会写:
select * from Table t where Color = 'blue'
但是我不知道如何使高亮显示的蓝色行上方的行。该示例是Excel,但仅为了便于生成示例。现实生活中的“蓝色”包含了更多的联接和数据,但是对于一个最低限度的完整示例来说,这是可行的。假定日期并非总是按日期时间排序,但是我总是希望该日期紧接在“蓝色”项之前,即日期时间。
答案 0 :(得分:3)
如果没有重复的日期,则使用UNION ALL:
select * from Table where Color = 'blue'
union all
select * from Table t
where
t.Color is null
and
(
select color from Table where date = (
select min(date) from Table where date > t.date)
) = 'blue'
order by date
答案 1 :(得分:0)
您是否可以向行添加唯一标识,例如整数ID?
如果您能够可靠地建立蓝色行的ID,则可以查询blueRowID-1。这似乎是解决问题的最直接方法。
答案 2 :(得分:0)
类似于@forpas,但使用LEAD
:
WITH -- sample data (using dt as the column name to avoid - using reserved words) t(dt, color) AS ( SELECT '2019-02-15 10:31:30.993', NULL UNION ALL SELECT '2019-02-15 17:15:46.910', 'blue' UNION ALL SELECT '2019-02-16 10:21:22.793', NULL UNION ALL SELECT '2019-02-19 10:30:34.827', NULL UNION ALL SELECT '2019-02-20 09:00:51.127', 'blue' UNION ALL SELECT '2019-02-20 09:00:58.767', NULL UNION ALL SELECT '2019-02-20 10:30:42.757', NULL UNION ALL SELECT '2019-02-21 09:35:54.819', NULL UNION ALL SELECT '2019-02-22 09:59:42.813', 'blue' ), WithLead(dt, color, next_dt) AS ( SELECT *, LEAD(dt) OVER (ORDER BY dt ASC) FROM t ) SELECT * FROM t WHERE color = 'blue' UNION ALL SELECT WithLead.dt, WithLead.color FROM WithLead INNER JOIN t AS NextRow ON NextRow.dt = WithLead.next_dt WHERE NextRow.color = 'blue' ORDER BY dt
请注意,结尾处的ORDER BY
并非绝对必要,但可以为您提供期望结果中的顺序。
答案 3 :(得分:0)
您可以使用ROW_NUMBER将其排序,然后直接在其上方选择一个。
DECLARE @t TABLE ([Date] DATE,Color VARCHAR(20))
INSERT INTO @t([Date],Color) SELECT '12/31/2019',''
INSERT INTO @t([Date],Color) SELECT '01/01/2019',''
INSERT INTO @t([Date],Color) SELECT '01/02/2019','blue'
INSERT INTO @t([Date],Color) SELECT '01/03/2019',''
INSERT INTO @t([Date],Color) SELECT '01/04/2019',''
INSERT INTO @t([Date],Color) SELECT '01/05/2019','blue'
SELECT
*
FROM (
select *,ROW_NUMBER() OVER (ORDER BY [Date] ASC) AS [Row] from @t
) SetA
WHERE Color = 'blue'
OR SetA.[Row] IN (
SELECT [Row]-1 FROM (
select *,ROW_NUMBER() OVER (ORDER BY [Date] ASC) AS [Row] from @t
)a
WHERE Color = 'blue'
)
答案 4 :(得分:0)
只需逐步进行操作-如果您使用如下所示的CTE,则非常容易测试,在任何时候,您都可以选择一个CTE来验证它是否正确。
WITH WITH_INDEX AS
(
select *, ROW_NUMBER() OVER (ORDER BY [Date]) AS RN
from Table t
), BLUE AS
(
SELECT *
FROM WITH_INDEX
where Color = 'blue'
)
SELECT *
FROM BLUE
UNION ALL
SELECT WITH_INDEX.*
FROM WITH_INDEX
JOIN BLUE ON WITH_INDEX.RN = BLUE.RN - 1