【问题标题】:Select first non-missing values over multiple rows in SQL (Updated with example)在 SQL 中的多行中选择第一个非缺失值(更新示例)
【发布时间】:2017-09-24 18:11:54
【问题描述】:

我有一张客户姓名和履历信息表。但是,每个客户的表可以有超过 1 行,但所有客户仍按相同的 ID 分组。例如......下面的客户 12345 总共有 3 行。有些行会有名字,有些则没有。同样适用于姓氏、生日等。例如,以下是我们在单个表中拥有的客户 12345 的所有信息:

customerid | priority | firstname | lastname | birthdate | state |
12345      | 1        | null      | Doe      | 11051983  | null  |
12345      | 2        | John      | Does     | null      | TX    |
12345      | 3        | null      | null     | null      | Texas |

我需要将客户 12345 的行向上滚动到 1 行,并且它必须包含尽可能多的传记信息。我如何让 SQL 遍历并找到第一个非缺失值(名字、姓氏、生日等)并将这些值包含在客户 12345 的最后一行中?所以最终的结果应该是这样的:

customerid | firstname | lastname | birthdate | state |
12345      | John      | Doe      | 11051983  | TX    |

由于客户信息包含多行,我不相信我可以使用 Coalesce 功能。还有其他想法吗?

这必须在 SQL 中完成。

提前致谢!

【问题讨论】:

  • “第一个非缺失值” - 关于什么顺序?如果生日有 2 行,你在乎用的是哪一个吗?
  • 我在上面添加了一个示例来展示如何处理这个问题。每条记录都有一个优先级。最高优先级的第一个非空值将显示在表格中。
  • @GeorgeRodman,为什么 max 对此不起作用?
  • 因为我不一定想要生日的最高值,或者姓氏的最长字符串。我想要最高优先级记录中的第一个非空值。想象一下,上面的第三条记录的生日记录是 11051984。虽然该记录可能更大,但它并不是来自最高优先级的来源……这就是我想要的。因此,当我想要第一条记录的值时,MAX 会从第三条记录中提取生日,因为它的优先级更高。
  • @GeorgeRodman 我将答案从 MAX 修改为 SUBQUERIES,它可以满足您现在的需要。

标签: sql sql-server database


【解决方案1】:

我认为这个合并可以使用SUBQUERIES

来完成

输入

12345   NULL    NULL    NULL        Texas
12345   NULL    Does    11051983    NULL
12345   John    Doe     NULL        TX
12346   NULL    NULL    NULL        Texas
12346   NULL    Last    1245678     NULL
12346   First   Last2   NULL        TX

输入(查询)

declare @tbl table(customerid int,firstname varchar(100),lastname varchar(100),birthdate varchar(100),state varchar(100))
insert into @tbl
select 12345,null,'Does','11051983',null union
select 12345,'John','Doe',null,'TX' union
select 12345,null,null,null,'Texas' union
select 12346,null,'Last','1245678',null union
select 12346,'First','Last2',null,'TX' union
select 12346,null,null,null,'Texas'

主查询

SELECT DISTINCT
 CustomerID,
 (SELECT TOP 1 firstname FROM @tbl tbl2 WHERE tbl2.customerid=tbl.customerid AND firstname IS NOT NULL ORDER BY priority) FirstName 
,(SELECT TOP 1 lastname FROM @tbl tbl2 WHERE tbl2.customerid=tbl.customerid AND lastname IS NOT NULL ORDER BY priority) LastName 
,(SELECT TOP 1 birthdate FROM @tbl tbl2 WHERE tbl2.customerid=tbl.customerid AND birthdate IS NOT NULL ORDER BY priority) BirthDate 
,(SELECT TOP 1 state FROM @tbl tbl2 WHERE tbl2.customerid=tbl.customerid AND state IS NOT NULL ORDER BY priority) State 
FROM @tbl tbl

结果

12345   John    Does    11051983    TX
12346   First   Last2   1245678     TX

【讨论】:

    【解决方案2】:

    你可以这样做:

    SELECT MAX(firstname), MAX(lastname), MAX(birthday) FROM customer GROUP BY id
    

    请注意 - 如果客户 #1 有 2 个不同的名字,这只会输出最大的名字。

    【讨论】:

      【解决方案3】:

      For Sql server 2012+,

      SELECT TOP 1 FIRST_VALUE(firstname) OVER (
              PARTITION BY customerid ORDER BY CASE 
                      WHEN firstname IS NULL
                          THEN 0
                      ELSE 1
                      END DESC
                  ,prioritys
              ) firstname
          ,FIRST_VALUE(lastname) OVER (
              PARTITION BY customerid ORDER BY CASE 
                      WHEN lastname IS NULL
                          THEN 0
                      ELSE 1
                      END DESC
                  ,prioritys
              ) lastname
          ,FIRST_VALUE(birthdate) OVER (
              PARTITION BY customerid ORDER BY CASE 
                      WHEN birthdate IS NULL
                          THEN 0
                      ELSE 1
                      END DESC
                  ,prioritys
              ) birthdate
          ,FIRST_VALUE(states) OVER (
              PARTITION BY customerid ORDER BY CASE 
                      WHEN states IS NULL
                          THEN 0
                      ELSE 1
                      END DESC
                  ,prioritys
              ) states
      FROM @t
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-19
        • 1970-01-01
        • 1970-01-01
        • 2014-01-11
        • 1970-01-01
        • 2019-07-01
        • 1970-01-01
        • 2021-03-20
        相关资源
        最近更新 更多