选择具有相同 id 但为空的行,以及该 id 的另一列中的一些其他值

IT *_*her 9 sql-server t-sql

我只想获取具有值NULL和其他值而不是NULL特定用户名列的行。

如果该特定用户名的两行都为 null,或者两者都有一些非 null 的值,则它不应出现在输出中。如果同一个用户名有两行以上的空值和一些其他值,那么它们应该出现。

下面是示例示例和输出。如何使用 sql 查询来完成?

+----------+-------+
| username | col2  |
+----------+-------+
| a        | abc   |
| a        | ef    |
| b        | null  |
| b        | null  |
| c        | der   |
| c        | null  |
+----------+-------+
Run Code Online (Sandbox Code Playgroud)

输出

+----------+------+
| username | col2 |
+----------+------+
| c        | der  |
| c        | null |
+----------+------+
Run Code Online (Sandbox Code Playgroud)

Tar*_*ryn 12

您应该能够使用条件聚合来获取具有值 incol2和的用户名null

我建议在条件中使用 HAVING 子句。查询将类似于:

select username
from yourtable
group by username
having sum(case when col2 is not null then 1 else 0 end) = 1
  and sum(case when col2 is null then 1 else 0 end) = 1
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo。此查询按每个用户名对您的数据进行分组,然后使用条件逻辑来检查是否col2满足您想要的两个条件 - 其中col2不为空 col2为空。

然后您可以在子查询等中使用它来获取usernamecol2值:

select 
  t.username, 
  t.col2
from yourtable t
inner join
(
  select username
  from yourtable
  group by username
  having sum(case when col2 is not null then 1 else 0 end) = 1
    and sum(case when col2 is null then 1 else 0 end) = 1
) d
  on t.username = d.username
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo

如果您有不止col2一行同时包含null另一个值,那么您只需要HAVING稍微更改子句:

select 
  t.username, 
  t.col2
from yourtable t
inner join
(
  select username
  from yourtable
  group by username
  having sum(case when col2 is not null then 1 else 0 end) >= 1
    and sum(case when col2 is null then 1 else 0 end) >= 1
) d
  on t.username = d.username;
Run Code Online (Sandbox Code Playgroud)

参见SQL Fiddle with Demo


Pau*_*ite 8

另一种解决方案:

SELECT Y1.*
FROM dbo.yourtable AS Y1
WHERE Y1.username = ANY
(
    SELECT Y2.username 
    FROM dbo.yourtable AS Y2
    WHERE Y2.col2 IS NULL
    INTERSECT
    SELECT Y3.username 
    FROM dbo.yourtable AS Y3
    WHERE Y3.col2 IS NOT NULL
);
Run Code Online (Sandbox Code Playgroud)

执行计划

在类似的逻辑脉络中:

SELECT Y.* 
FROM dbo.yourtable AS Y
WHERE EXISTS
    (
    SELECT * 
    FROM dbo.yourtable AS Y2 
    WHERE Y2.username = Y.username 
    AND Y2.col2 IS NULL
    )
AND EXISTS
    (
    SELECT * 
    FROM dbo.yourtable AS Y3 
    WHERE Y3.username = Y.username 
    AND Y3.col2 IS NOT NULL
    );
Run Code Online (Sandbox Code Playgroud)

执行计划

完后还有:

SELECT
    SQ1.username,
    SQ1.col2
FROM 
(
    SELECT
        Y.username, 
        Y.col2,
        MinCol2 = 
            MIN(CASE WHEN Y.col2 IS NULL THEN -1 ELSE 1 END) 
            OVER (PARTITION BY Y.username), 
        MaxCol2 = 
            MAX(CASE WHEN Y.col2 IS NULL THEN -1 ELSE 1 END) 
            OVER (PARTITION BY Y.username)
    FROM dbo.yourtable AS Y
) AS SQ1
WHERE 
    SQ1.MinCol2 = -SQ1.MaxCol2;
Run Code Online (Sandbox Code Playgroud)

执行计划


ype*_*eᵀᴹ 5

只是另一种方法:

; WITH cte AS
  ( SELECT username, col2,
           cnt_all  = COUNT(*) OVER (PARTITION BY username),
           not_null = COUNT(col2) OVER (PARTITION BY username)
    FROM yourtable AS a
  )
SELECT username, col2
FROM cte
WHERE cnt_all > not_null 
  AND not_null > 0 ;
Run Code Online (Sandbox Code Playgroud)