我只想获取具有值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为空。
然后您可以在子查询等中使用它来获取username和col2值:
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)
如果您有不止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)
另一种解决方案:
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)

只是另一种方法:
; 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)