【问题标题】:Skipping NULL values in column assignment在列分配中跳过 NULL 值
【发布时间】:2019-05-31 12:28:47
【问题描述】:

有一个包含地址信息的数据库表

+--------------------------------------------------------------+
| name1       | name2 | name3 | street        | zip     | city |
+--------------------------------------------------------------+
| 'Some name' | NULL  | ''    | 'Some street' | '12345' | NULL |
+--------------------------------------------------------------+

因此某些字段可能为 NULL 或空。

现在我要选择

SELECT
  name1,  /* 'Some name' */
  name2,  /* NULL */
  name3,  /* '' */
  street, /* 'Some street' */
  zip,    /* '12345' */
  city,   /* NULL */

  adr1,   /* Should contain 'Some name' */
  adr2,   /* Should contain 'Some street' */
  adr3,   /* Should contain '12345' */
  adr4,   /* NULL */
  adr5,   /* NULL */
  adr6    /* NULL */
FROM
 adr

其中adr16 代表信头行,应按name1name2name3streetstreetzipcity 的顺序填充,但应跳过 NULL 或赋值时为空值。

有人知道如何实现这一目标吗?

【问题讨论】:

  • 你试过WHERE...吗?
  • 显示您想要的预期结果。 adr1...adr6 的列来自哪里?
  • 您能否提供更多有关期望的详细信息-您期望的结果是什么(您可以举个例子)。如果您根本不想返回空列,则可以在应用程序代码中处理。
  • 这张表有主键列吗?
  • adr16 的列是“虚拟的”。问题是如何分配它们。

标签: sql sql-server sql-server-2016


【解决方案1】:

这有点混乱,并且依赖于您有一个 ID 列,但是,我认为这就是您所追求的:

WITH CTE AS(
    SELECT S.YourID,
           S.name1,
           S.name2,
           S.name3,
           S.street,
           S.zip,
           S.city,
           NULLIF(V.Adr,'') AS Adr,
           Line,
           ROW_NUMBER() OVER (PARTITION BY YourID, CASE WHEN NULLIF(V.Adr,'') IS NULL THEN 1 ELSE 0 END ORDER BY Line) AS RN
    FROM (VALUES(1, 'Some name',CONVERT(varchar(10),NULL),'','Some street','12345',CONVERT(varchar(10),NULL))) S(YourID,name1,name2,name3,street,zip,city)
         CROSS APPLY(VALUES(name1,1),(name2,2),(name3,3),(street,3),(zip,4),(city,5)) V(Adr,Line))
SELECT C.YourID,
       MAX(C.name1) AS name1,
       MAX(C.name2) AS name2,
       MAX(C.name3) AS name3,
       MAX(C.street) AS street,
       MAX(C.zip) AS zip,
       MAX(C.city) AS city,
       MAX(CASE WHEN C.RN = 1 THEN C.Adr END) AS Adr1,
       MAX(CASE WHEN C.RN = 2 THEN C.Adr END) AS Adr2,
       MAX(CASE WHEN C.RN = 3 THEN C.Adr END) AS Adr3,
       MAX(CASE WHEN C.RN = 4 THEN C.Adr END) AS Adr4,
       MAX(CASE WHEN C.RN = 5 THEN C.Adr END) AS Adr5,
       MAX(CASE WHEN C.RN = 6 THEN C.Adr END) AS Adr6
FROM CTE C
WHERE C.Adr IS NOT NULL
GROUP BY C.YourID;

【讨论】:

  • 是的,看起来很乱——尤其是当“真实”选择包含来自 7 个表格的大约 50 列时:/
  • 我只能以我们有 @Inceddy 的单个示例为基础。如果您的样本数据不能代表您的真实数据,那么答案也不会是。
  • 该示例仅描述了问题并遗漏了任何元信息。您的回答确实解决了问题,但它不是“漂亮”^^
  • @Inceddy 如果此建议有效(如您所说),请将其标记为答案以关闭问题并让其他人找到类似问题的解决方案。
猜你喜欢
  • 2019-05-18
  • 1970-01-01
  • 1970-01-01
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-15
  • 1970-01-01
相关资源
最近更新 更多