Выберите строки, в которых столбец не равен NULL, если несколько значений, или NULL, если 1 значение - PullRequest
1 голос
/ 14 марта 2019

У меня есть таблица, содержащая заголовки и значения.

Для отдельного заголовка я хочу получить все ненулевые значения, кроме случаев, когда этот заголовок имеет только значение 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

Я могу добиться извлечения всех значений, кроме NULL, с помощью следующего запросано я заблокирован для случая, если заголовок имеет только значение NULL:

select distinct Title, Value 
from mytable
where Value is not null

Ответы [ 7 ]

4 голосов
/ 14 марта 2019

Вы можете использовать НЕ СУЩЕСТВУЕТ:

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
                    )
2 голосов
/ 14 марта 2019

Вы можете избежать использования союзов, если хотите, и попробуйте это:

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;

Я бы посоветовал попробовать все эти параметры в зависимости от формы ваших реальных данных, чтобы найти наиболее эффективную версию. Также стоит потратить некоторое время на проверку индексов и т. Д., Чтобы сделать их быстрее.

1 голос
/ 14 марта 2019

Другие опции:

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 по сравнению с объединением. Будет зависеть от того, сколько данных входит, хотя сортировка может стать более дорогой, чем объединение, хотя для версии объединения требуется сортировка для различных типов.

Дайте им попробовать реальные данные и получите немного времени. дайте мне знать, если это поможет.

1 голос
/ 14 марта 2019

Другой вариант - использовать объединение и подзапрос

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    
0 голосов
/ 14 марта 2019
SELECT      
    DISTINCT a.Title,           
             b.Value   
FROM      
    mytable a   
LEFT JOIN 
    mytable b 
ON  
    a.Title = b.Title 
AND  
    b.Value IS NOT NULL;
0 голосов
/ 14 марта 2019

Я могу предложить ниже решение вашей проблемы,

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
0 голосов
/ 14 марта 2019

Попробуйте это

;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

Результат

Title   Value
-------------
ex1      8
ex1      9
ex2      8
ex3      NULL
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...