【问题标题】:TSQL Coalesce Row valuesTSQL 合并行值
【发布时间】:2019-07-07 20:32:26
【问题描述】:

我目前有一个非常简单的查询,只需选择并生成以下内容

| Date       | Name             | ID      |
|------------|------------------|---------|
| 2018-11-07 | McDonald's       | 1046226 |
| 2018-01-22 | NULL             | 1046226 |
| 2019-01-07 | Dell             | 1069285 |
| 2019-01-09 | Dell Corporation | 1069285 |

我想要做的是为每个 ID 选择最早的日期行,使用 MIN

但我遇到的问题是,如果最早的行有一个 NULL 名称,我想从另一行合并它的名称

| Date       | Name             | ID      |
|------------|------------------|---------|
| 2018-01-22 | McDonald's       | 1046226 |
| 2019-01-07 | Dell             | 1069285 |

我不知道这里是否有任何语法可以帮助我,有人可以帮忙吗?

【问题讨论】:

    标签: sql sql-server tsql azure-sqldw


    【解决方案1】:

    coalesce:

    select 
      min(t.date) Date,
      coalesce(
        (
          select name from tablename where id = t.id and date = (
            select min(date) from tablename where id = t.id
          )
        ),
        max(name)
      ) name,
      t.id ID
    from tablename t
    group by t.id
    

    【讨论】:

    • 我认为您最简单的解决方案在您编辑它之前有效,当时它只是 MAX(NAME) 和 MIN(DATE)
    • 是的,它确实有效,但如果名称不为空,那么它将从另一行获取另一个名称。
    • 只有当最小日期的名称为空时,当前代码才获得另一个名称。
    • 哦,我明白了,所以在我上面的示例中,第二行不一定是戴尔而是戴尔公司(如果戴尔公司>戴尔)。我认为这种情况还是可以的。谢谢!
    • 使用适合你的版本。
    【解决方案2】:

    通常,row_number() 用于此目的:

    select t.*
    from (select t.*, row_number() over (partition by id order by date) as seqnum
          from <your query here> t
         ) t
    where seqnum = 1;
    

    一种更简单但速度可能稍慢的方法是:

    select top (1) with ties . . .
    from . . .
    . . .
    order by row_number() over (partition by id order by date)
    

    【讨论】:

      【解决方案3】:

      使用 CTE 在 Azure SQL 数据仓库上测试的两种方法

      ;WITH cte AS
      (
      SELECT *, ROW_NUMBER() OVER( PARTITION BY ID ORDER BY [Date] ) rn
      FROM #tmp
      )
      SELECT [Date], name, ID 
      FROM cte 
      WHERE rn = 1
      

      或者如果您想将剩余数据 CTAS 到一个新表中,您可以在 Azure SQL 数据仓库中结合 CTE 和 CTAS,例如

      CREATE TABLE dbo.yourNewTable
      WITH
      (
          CLUSTERED COLUMNSTORE INDEX,
          DISTRIBUTION = HASH( ID )
          -- Optionally add partition scheme here if required
      )
      AS
      WITH cte AS
      (
      SELECT
          [Date],
          MIN(Name) OVER( PARTITION BY ID ) name,
          ID,
          ROW_NUMBER() OVER( PARTITION BY ID ORDER BY [Date] ) rn
      FROM dbo.yourTable
      )
      SELECT [Date], name, ID 
      FROM cte 
      WHERE rn = 1
      OPTION ( LABEL = 'CTAS : Dedupe' );
      

      注意RANKROW_NUMBER 的行为差异。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-11-21
        • 1970-01-01
        • 2012-06-30
        • 2013-05-09
        • 2011-06-23
        • 1970-01-01
        • 1970-01-01
        • 2016-12-24
        相关资源
        最近更新 更多