【问题标题】:SQL Query to find earliest date dependent on column value changingSQL查询根据列值变化查找最早日期
【发布时间】:2010-01-09 16:55:35
【问题描述】:

我有一个问题,我需要从按列分组但按顺序分组的表中获取最早的日期值。

这是一个示例表:

if object_id('tempdb..#tmp') is NOT null 
    DROP TABLE #tmp

CREATE TABLE #tmp
(
    UserID              BIGINT      NOT NULL,
    JobCodeID           BIGINT      NOT NULL,
    LastEffectiveDate   DATETIME    NOT NULL
)

INSERT INTO #tmp VALUES ( 1, 5, '1/1/2010') 
INSERT INTO #tmp VALUES ( 1, 5, '1/2/2010') 
INSERT INTO #tmp VALUES ( 1, 6, '1/3/2010') 
INSERT INTO #tmp VALUES ( 1, 5, '1/4/2010') 
INSERT INTO #tmp VALUES ( 1, 1, '1/5/2010') 
INSERT INTO #tmp VALUES ( 1, 1, '1/6/2010')

SELECT JobCodeID, MIN(LastEffectiveDate)
FROM #tmp
WHERE UserID = 1
GROUP BY JobCodeID

DROP TABLE [#tmp]

此查询将返回 3 行,其中包含最小值。

1   2010-01-05 00:00:00.000
5   2010-01-01 00:00:00.000
6   2010-01-03 00:00:00.000

我正在寻找的是该组是连续的并返回多个 JobCodeID,如下所示:

5   2010-01-01 00:00:00.000
6   2010-01-03 00:00:00.000
5   2010-01-04 00:00:00.000
1   2010-01-05 00:00:00.000

没有光标可以吗?

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:
    SELECT  JobCodeId, MIN(LastEffectiveDate) AS mindate
    FROM    (
            SELECT  *,
                    prn - rn AS diff
            FROM    (
                    SELECT  *,
                            ROW_NUMBER() OVER (PARTITION BY JobCodeID 
                                        ORDER BY LastEffectiveDate) AS prn,
                            ROW_NUMBER() OVER (ORDER BY LastEffectiveDate) AS rn
                    FROM    @tmp
                    ) q
            ) q2
    GROUP BY
            JobCodeId, diff
    ORDER BY
            mindate
    

    连续范围在分区和未分区ROW_NUMBERs之间具有相同的区别。

    您可以在GROUP BY 中使用此值。

    有关其工作原理的更多详细信息,请参阅我的博客中的这篇文章:

    【讨论】:

      【解决方案2】:

      第一条评论 - 使用表变量而不是临时表会更好。然后你可以使用这样的技巧。确保以正确的顺序插入值(即 LastEffectiveDate 升序):

      DECLARE @tmp table
      (
          Sequence            INT IDENTITY,
          UserID              BIGINT,
          JobCodeID           BIGINT,
          LastEffectiveDate   DATETIME
      )
      
      INSERT INTO @tmp VALUES ( 1, 5, '1/1/2010') 
      INSERT INTO @tmp VALUES ( 1, 5, '1/2/2010') 
      INSERT INTO @tmp VALUES ( 1, 6, '1/3/2010') 
      INSERT INTO @tmp VALUES ( 1, 5, '1/4/2010') 
      INSERT INTO @tmp VALUES ( 1, 1, '1/5/2010') 
      INSERT INTO @tmp VALUES ( 1, 1, '1/6/2010')
      
      SELECT TOP 1 JobCodeID, LastEffectiveDate
      FROM @tmp
      
      UNION ALL
      
      SELECT t2.JobCodeID, t2.LastEffectiveDate
      FROM @tmp t1
          INNER JOIN
              @tmp t2
              ON t1.Sequence + 1 = t2.Sequence
      WHERE t1.JobCodeID <> t2.JobCodeID
      

      每次工作代码更改时都会输出第一个日期,我猜这就是你想要的描述。

      【讨论】:

      • 请注意在粘贴和运行之前进行编辑 - ORDER BY 破坏了它。
      • 临时表是为了代表一个现有的表,这就是我使用它的原因。我有一个需要使用查询的实际表。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-10
      • 2012-08-18
      • 2021-08-11
      • 2016-04-30
      • 2020-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多