Sql 如果有多个值,则选择列不为null的行;如果有1个值,则选择列不为null的行
我有一个包含标题和值的表 对于不同的标题,我希望检索所有非空值,除非该标题只有空值 我的表格示例如下所示:Sql 如果有多个值,则选择列不为null的行;如果有1个值,则选择列不为null的行,sql,sql-server,Sql,Sql Server,我有一个包含标题和值的表 对于不同的标题,我希望检索所有非空值,除非该标题只有空值 我的表格示例如下所示: Title Value --------------- ex1 8 ex1 9 ex1 NULL ex2 8 ex2 NULL ex3 NULL Libelle TPO_code -------------------- ex1 8 ex1 9 ex2
Title Value
---------------
ex1 8
ex1 9
ex1 NULL
ex2 8
ex2 NULL
ex3 NULL
Libelle TPO_code
--------------------
ex1 8
ex1 9
ex2 8
ex3 NULL
在本例中,我希望所需的输出如下所示:
Title Value
---------------
ex1 8
ex1 9
ex1 NULL
ex2 8
ex2 NULL
ex3 NULL
Libelle TPO_code
--------------------
ex1 8
ex1 9
ex2 8
ex3 NULL
我可以通过以下请求检索除空值以外的所有值,但由于标题只有空值,我被阻止:
select distinct Title, Value
from mytable
where Value is not null
您可以使用不存在的文件:
SELECT DISTINCT T.Title
, T.Value
FROM mytable T
WHERE T.Value IS NOT NULL
OR NOT EXISTS (
SELECT NULL
FROM mytable T2
WHERE T2.Value IS NOT NULL
AND T2.Title = T1.Title
)
您可以使用不存在的文件:
SELECT DISTINCT T.Title
, T.Value
FROM mytable T
WHERE T.Value IS NOT NULL
OR NOT EXISTS (
SELECT NULL
FROM mytable T2
WHERE T2.Value IS NOT NULL
AND T2.Title = T1.Title
)
另一种选择是使用联合和子查询
declare @t table (Title varchar(10), Value int)
insert into @t (Title, Value)
values ('ex1', 8), ('ex1', 9), ('ex1', null), ('ex2', 8), ('ex2', null), ('ex3', null)
-- first get all rows with Value different from null
select t.Title,
t.Value
from @t t
where t.Value is not null
union
-- now also get all rows with just one row and where that row has null in value
select t.Title,
t.Value
from @t t
where t.Title in ( select t2.title from @t t2 group by t2.Title having count(t2.Title) = 1 )
and t.Value is null
这将返回此结果
Title Value
----- -----
ex1 8
ex1 9
ex2 8
ex3 null
另一种选择是使用联合和子查询
declare @t table (Title varchar(10), Value int)
insert into @t (Title, Value)
values ('ex1', 8), ('ex1', 9), ('ex1', null), ('ex2', 8), ('ex2', null), ('ex3', null)
-- first get all rows with Value different from null
select t.Title,
t.Value
from @t t
where t.Value is not null
union
-- now also get all rows with just one row and where that row has null in value
select t.Title,
t.Value
from @t t
where t.Title in ( select t2.title from @t t2 group by t2.Title having count(t2.Title) = 1 )
and t.Value is null
这将返回此结果
Title Value
----- -----
ex1 8
ex1 9
ex2 8
ex3 null
试试这个
;WITH CTE (Title, Value)
AS
(
SELECT 'ex1', 8 UNION ALL
SELECT 'ex1', 9 UNION ALL
SELECT 'ex1', NULL UNION ALL
SELECT 'ex2', 8 UNION ALL
SELECT 'ex2', NULL UNION ALL
SELECT 'ex3', NULL
)
,CTe2
AS
(
SELECT Title, Value, COUNT(Title)OVER(PARTITION BY Title ORDER BY Title) cnt
FROM CTE
)
SELECT Title,
Value
FROM CTe2 WHERE ISNULL(Value,1) <> 1
UNION ALL
SELECT Title,
Value
FROM CTe2 WHERE cnt =1
试试这个
;WITH CTE (Title, Value)
AS
(
SELECT 'ex1', 8 UNION ALL
SELECT 'ex1', 9 UNION ALL
SELECT 'ex1', NULL UNION ALL
SELECT 'ex2', 8 UNION ALL
SELECT 'ex2', NULL UNION ALL
SELECT 'ex3', NULL
)
,CTe2
AS
(
SELECT Title, Value, COUNT(Title)OVER(PARTITION BY Title ORDER BY Title) cnt
FROM CTE
)
SELECT Title,
Value
FROM CTe2 WHERE ISNULL(Value,1) <> 1
UNION ALL
SELECT Title,
Value
FROM CTe2 WHERE cnt =1
如果需要,可以避免使用联合体,并尝试以下方法:
DECLARE @myTable AS TABLE (Title CHAR(4) NOT NULL, Value INT NULL);
INSERT INTO @myTable (Title, Value)
VALUES ('ex1', 8)
, ('ex1', 9)
, ('ex1', NULL)
, ('ex2', 8)
, ('ex2', NULL)
, ('ex3', NULL);
SELECT DISTINCT
T1.Title
, T2.Value
FROM @myTable T1
LEFT JOIN @myTable T2 ON T2.Title = T1.Title
AND T2.Value IS NOT NULL;
我建议您根据实际数据的形状尝试所有这些选项,以找到最有效的版本。也值得花一些时间检查索引等,以使这些更快 如果需要,可以避免使用联合体,并尝试以下方法:
DECLARE @myTable AS TABLE (Title CHAR(4) NOT NULL, Value INT NULL);
INSERT INTO @myTable (Title, Value)
VALUES ('ex1', 8)
, ('ex1', 9)
, ('ex1', NULL)
, ('ex2', 8)
, ('ex2', NULL)
, ('ex3', NULL);
SELECT DISTINCT
T1.Title
, T2.Value
FROM @myTable T1
LEFT JOIN @myTable T2 ON T2.Title = T1.Title
AND T2.Value IS NOT NULL;
我建议您根据实际数据的形状尝试所有这些选项,以找到最有效的版本。也值得花一些时间检查索引等,以使这些更快 我可以为您的问题提出以下解决方案
select title,value from mytable where id is not null
union
select title,value from (
select title,value, dense_rank() over (partition by title order by value) rank from mytable)
where rank=1
我可以为您的问题提出以下解决方案
select title,value from mytable where id is not null
union
select title,value from (
select title,value, dense_rank() over (partition by title order by value) rank from mytable)
where rank=1
其他选择:
DECLARE @myTable AS TABLE (Title CHAR(4) NOT NULL, Value INT NULL);
INSERT INTO @myTable (Title, Value)
VALUES ('ex1', 8)
, ('ex1', 9)
, ('ex1', NULL)
, ('ex2', 8)
, ('ex2', NULL)
, ('ex3', NULL);
-- Original
SELECT DISTINCT
T1.Title
, T2.Value
FROM @myTable T1
LEFT JOIN @myTable T2 ON T2.Title = T1.Title
AND T2.Value IS NOT NULL;
-- Common Table Expression example
WITH cte AS
(SELECT *
, ROW_NUMBER() OVER (PARTITION BY Title
ORDER BY Value DESC) RN
FROM @myTable)
SELECT cte.Title
, cte.Value
FROM cte
WHERE RN = 1
OR cte.Value IS NOT NULL
如果运行公共表表达式并指定行号,则可以确保每个“标题”至少有一行,而不会出现多个表命中。如果你同时运行两个执行计划,我会看到cte版本在连接上的保存。尽管排序可能比联接更昂贵,但是联接版本需要对distinct进行排序,这将取决于传入的数据量
让他们尝试一下真实的数据,并获得一些时间安排。如果有帮助,请告诉我。其他选项:
DECLARE @myTable AS TABLE (Title CHAR(4) NOT NULL, Value INT NULL);
INSERT INTO @myTable (Title, Value)
VALUES ('ex1', 8)
, ('ex1', 9)
, ('ex1', NULL)
, ('ex2', 8)
, ('ex2', NULL)
, ('ex3', NULL);
-- Original
SELECT DISTINCT
T1.Title
, T2.Value
FROM @myTable T1
LEFT JOIN @myTable T2 ON T2.Title = T1.Title
AND T2.Value IS NOT NULL;
-- Common Table Expression example
WITH cte AS
(SELECT *
, ROW_NUMBER() OVER (PARTITION BY Title
ORDER BY Value DESC) RN
FROM @myTable)
SELECT cte.Title
, cte.Value
FROM cte
WHERE RN = 1
OR cte.Value IS NOT NULL
SELECT
DISTINCT a.Title,
b.Value
FROM
mytable a
LEFT JOIN
mytable b
ON
a.Title = b.Title
AND
b.Value IS NOT NULL;
如果运行公共表表达式并指定行号,则可以确保每个“标题”至少有一行,而不会出现多个表命中。如果你同时运行两个执行计划,我会看到cte版本在连接上的保存。尽管排序可能比联接更昂贵,但是联接版本需要对distinct进行排序,这将取决于传入的数据量
让他们尝试一下真实的数据,并获得一些时间安排。如果这有帮助,请告诉我。很好的发现,我没有想到使用联接来实现此目的。通常这是我第一次尝试,因为它通常是最有效的+1@GuidoG-谢谢。这只是另一种选择。在不知道数据/索引等形状的情况下,总是要尝试一下,看看什么是最快的。我试图想出一种方法来做到这一点,而不必两次击中表-我将在一分钟后发布我的另一个选项查找,我没有想到使用连接。通常这是我第一次尝试,因为它通常是最有效的+1@GuidoG-谢谢。这只是另一种选择。在不知道数据/索引等形状的情况下,总是要尝试一下,看看什么是最快的。我在想一种不必两次点击表格的方法-我会在一分钟内发布我的另一个选项在我的数据上使用这个选项更快(3分钟10秒),尽管它只给我排名1。我将其调整为所有等级,如果标题的等级>2,则除空等级外。谢谢你的时间!哎呀,我的代码漏掉了底线。再来一次,看看这与你所调整的相比如何。能够从部分答案中得出解决方案通常更有用,因为这表明您已经理解了。在我的数据中,使用此选项更快(3分钟约10秒),尽管它只给我排名1。我将其调整为所有等级,如果标题的等级>2,则除空等级外。谢谢你的时间!哎呀,我的代码漏掉了底线。再来一次,看看这与你所调整的相比如何。能够从部分答案中找出答案通常更有用,因为这表明你已经理解了。
SELECT
DISTINCT a.Title,
b.Value
FROM
mytable a
LEFT JOIN
mytable b
ON
a.Title = b.Title
AND
b.Value IS NOT NULL;