Выберите только наиболее полную запись - PullRequest
0 голосов
/ 26 ноября 2018

Мне нужно решить следующую проблему.

Предположим, у меня есть таблица с 4 полями, которая называется a, b, c, d.

У меня есть следующие записи:

-------------------------------------
   a   |    b    |    c    |    d  
-------------------------------------
   1   |    2    |         |             row 1 
   1   |    2    |    3    |    4        row 2 
   1   |    2    |         |    4        row 3
   1   |    2    |    3    |             row 4  

Как можно заметить, строки 1,3,4 - это "подзаписи" строки 2.

Я хотел бы извлечь только 2-ую строку.

Не могли бы вы помочь мне, пожалуйста?

Заранее спасибо за ответ

РЕДАКТИРОВАТЬ: мне нужно быть более конкретным.

У меня могут быть также случаи:

-------------------------------------
   a   |    b    |    c    |    d  
-------------------------------------
   1   |    2    |         |             row 1 
   1   |    2    |         |    4        row 2 
   1   |         |         |    4        row 3

, где мне нужно извлечь 2-й ряд,

-------------------------------------
   a   |    b    |    c    |    d  
-------------------------------------
   1   |    2    |         |             row 1 
   1   |    2    |    3    |             row 2 
   1   |         |    3    |             row 3

и снова мне нужно извлечь 2-й ряд.

То же самое для пар,


   a   |    b    |    c    |    d  
-------------------------------------
   1   |         |         |             row 1 
   1   |         |    3    |             row 2 
       |         |    3    |             row 3

и т. Д. Для других примеров.

(Конечно, теперь это всегда 2-й ряд)

Ответы [ 5 ]

0 голосов
/ 26 ноября 2018

Используя NOT EXISTS, можно отфильтровать записи с лучшим дубликатом.

create table abcd (
 a int,
 b int,
 c int,
 d int
);
insert into abcd (a, b, c, d) values
 (1, 2, null, null)
,(1, 2, 3, 4)
,(1, 2, null, 4)
,(1, 2, 3, null)

,(2, 3, null,null)
,(2, 3, null, 5)
,(2, null, null, 5) 

,(3, null, null, null)
,(3, null, 5, null)
,(null, null, 5, null)
SELECT *  
FROM abcd AS t 
WHERE NOT EXISTS 
(
   select 1
   from abcd as d  
   where (t.a is null or d.a = t.a)
     and (t.b is null or d.b = t.b)
     and (t.c is null or d.c = t.c)
     and (t.d is null or d.d = t.d)
     and (case when t.a is null then 0 else 1 end +
          case when t.b is null then 0 else 1 end +
          case when t.c is null then 0 else 1 end +
          case when t.d is null then 0 else 1 end) < 
         (case when d.a is null then 0 else 1 end +
          case when d.b is null then 0 else 1 end +
          case when d.c is null then 0 else 1 end +
          case when d.d is null then 0 else 1 end)
);
 a |    b |    c |    d
-: | ---: | ---: | ---:
 1 |    2 |    3 |    4
 2 |    3 | <em>null</em> |    5
 3 | <em>null</em> |    5 | <em>null</em>

дБ <> скрипка здесь

0 голосов
/ 26 ноября 2018

Как уже упоминал Гордон Линофф, нам тоже нужно использовать что-то вроде несуществующего,

Редактировать Использование EXCEPT помогает

Это может сработать ...

SELECT * from table1 
EXCEPT
(
SELECT t1.*
FROM table1 t1
JOIN table1 t2
ON  COALESCE(t1.a, t2.a, -1) = COALESCE(t2.a, -1)
AND COALESCE(t1.b, t2.b, -1) = COALESCE(t2.b, -1)
AND COALESCE(t1.c, t2.c, -1) = COALESCE(t2.c, -1)
AND COALESCE(t1.d, t2.d, -1) = COALESCE(t2.d, -1)
)

Здесь t1 - каждая строка подмножества.

Примечание. Мы принимаем значение -1 в качестве значения часового, и оно не встречается ни в одном столбце.

0 голосов
/ 26 ноября 2018

Хммм.,,Я думаю, что вы можете использовать not exists:

with t as (
      select t.*, row_number() over (order by a) as id
      from t
     )
select t.*
from t
where not exists (select 1
                  from t t2
                  where ((t2.a is not distinct from t.a or t2.a is not null and t.a is null) and
                         (t2.b is not distinct from  t.b or t2.b is not null and t.b is null) and
                         (t2.c is not distinct from  t.c or t2.c is not null and t.c is null) and
                         (t2.d is not distinct from  t.d or t2.d is not null and t.d is null)
                        ) and
                        t2.id <> t.id
                 );

Логика заключается в том, что не существует более конкретной строки, где значения соответствуют

Здесь - это дБ <>скрипка.

0 голосов
/ 26 ноября 2018

Вам нужно будет вычислить «индекс завершения» для каждой строки.В приведенном вами примере вы можете использовать что-то вроде:

   (CASE WHEN a IS NULL THEN 0 ELSE 1) +
   (CASE WHEN b IS NULL THEN 0 ELSE 1) +
   (CASE WHEN c IS NULL THEN 0 ELSE 1) +
   (CASE WHEN d IS NULL THEN 0 ELSE 1) AS CompletionIndex

Затем ВЫБЕРИТЕ верхнюю 1, упорядоченную CompletionIndex в порядке убывания.большое количество столбцов.Но если у вас есть большое количество малонаселенных столбцов, вы можете рассмотреть структуру данных на основе строк, а не столбцов.Такой дизайн значительно облегчит подсчет числа ненулевых значений для каждого объекта.

0 голосов
/ 26 ноября 2018

Наиболее полные строки, по вашему определению, это строки с наименьшим нулевым столбцом:

SELECT * FROM tablename
WHERE (
    (CASE WHEN a IS NULL THEN 0 ELSE 1 END) + 
    (CASE WHEN b IS NULL THEN 0 ELSE 1 END) + 
    (CASE WHEN c IS NULL THEN 0 ELSE 1 END) + 
    (CASE WHEN d IS NULL THEN 0 ELSE 1 END)
) =
(SELECT MAX(
    (CASE WHEN a IS NULL THEN 0 ELSE 1 END) + 
    (CASE WHEN b IS NULL THEN 0 ELSE 1 END) + 
    (CASE WHEN c IS NULL THEN 0 ELSE 1 END) + 
    (CASE WHEN d IS NULL THEN 0 ELSE 1 END)) 
FROM tablename)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...