【问题标题】:how to get rows with null values and value如何获取具有空值和值的行
【发布时间】:2015-11-13 16:08:04
【问题描述】:

面试官问我以下问题:

考虑下表:

tpid data
100 1
100 2
100 NULL
101 6
101 5
101 NULL
102 NULL
103 9
103 65
104 NULL
..
..

如果tpid 有任何数据,则显示数据而不是空值 但如果 tpid 只得到 null 则只针对 id 显示 null。

结果集应该是这样的:

tpid data
100 1
100 2
101 6
101 5
102 NULL
103 9
103 65
104 NULL

我写了以下查询,但它没有给出想要的结果:

;with cte as
(select tpid,count(data) as num from a group by TPID)

 select a.TPID,
 (case when cte.num=0 then NULL else a.DATA end)col
 from cte
join A on a.TPID=cte.TPID

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:
    DECLARE @temp TABLE(tpid int, data int)
    
    INSERT INTO @temp 
    SELECT 100, 1 UNION
    SELECT 100, 2UNION
    SELECT 100, NULL UNION
    SELECT 101, 6 UNION
    SELECT 101, 5 UNION
    SELECT 101, NULL UNION
    SELECT 102, NULL UNION
    SELECT 103, 9 UNION
    SELECT 103, 65 UNION
    SELECT 104, NULL
    
    
    
    
    SELECT * FROM @temp a WHERE 
    data IS not NULL OR (select COUNT(1) FROM @temp WHERE tpid=a.tpid)=1
    

    答案:

    tpid    data
    100     1
    100     2
    101     5
    101     6
    102    NULL
    103     9
    103    65
    104   NULL
    

    【讨论】:

      【解决方案2】:

      你可以使用窗口函数来得到你想要的:

      SELECT tpid, data
      FROM (
        SELECT tpid, data,
               COUNT(*) OVER (PARTITION BY tpid) AS cnt,
               COUNT(CASE WHEN [data] IS NULL THEN 1 END) 
               OVER (PARTITION BY tpid) AS cntNulls
        FROM mytable) AS t
        WHERE (data IS NOT NULL) OR (cnt = cntNulls)
      

      NULL 值被过滤掉,除非tpid 切片中只有 NULL 值。

      Demo here

      您也可以使用以下查询:

      SELECT t1.tpid, t1.data
      FROM mytable AS t1
      LEFT JOIN (
        SELECT tpid
        FROM mytable
        GROUP BY tpid
        HAVING COUNT(*) = COUNT(CASE WHEN data IS NULL THEN 1 END)
      ) AS t2 ON t1.tpid = t2.tpid
      WHERE (t1.data IS NOT NULL) OR (t2.tpid IS NOT NULL)
      

      Demo here

      【讨论】:

        【解决方案3】:
        select tpid,data from (SELECT tpid, data,
                 COUNT(*) OVER (PARTITION BY tpid) AS cnt,
                 COUNT(CASE WHEN [data] IS NULL THEN 1 END) 
                 OVER (PARTITION BY tpid) AS cntNulls
          FROM mytable) t
          where t.cntNulls = t.cnt or data is not null
        

        【讨论】:

        • 这看起来像是我的答案的复制/粘贴
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 1970-01-01
        相关资源
        最近更新 更多