SQL查询以在表中获得一个“行”

时间:2019-04-25 18:06:59

标签: sql-server

我需要从SQL中的一个表中获取结果列表,以便我需要在where语句选择的日期之前紧跟其日期值的行。在下图中,我会写:

select * from Table t where Color = 'blue'

但是我不知道如何使高亮显示的蓝色行上方的行。该示例是Excel,但仅为了便于生成示例。现实生活中的“蓝色”包含了更多的联接和数据,但是对于一个最低限度的完整示例来说,这是可行的。假定日期并非总是按日期时间排序,但是我总是希望该日期紧接在“蓝色”项之前,即日期时间。

enter image description here

5 个答案:

答案 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