SQL элегантность: можно ли избежать этого подбора? - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть оператор SQL, в котором предложение subselect where очень похоже на предложение where.Это заставляет меня задуматься, есть ли более чистый способ выразить это.

Данные получают обновления каждый месяц, и каждая строка данных получает дату начала, когда она появилась, и дату окончания, когда она больше не появляется.Он может больше не появляться из-за полного исчезновения линии данных или из-за того, что линия данных вообще не изменяется.Любой данный идентификатор может иметь 1 или несколько строк данных.Мой внутренний выбор находит все идентификаторы, где любая из строк была недавно изменена / удалена, а внешний выбор находит все строки с теми идентификаторами, которые либо являются текущими, либо недавно были изменены / удалены.Это работает в Netezza.

select A.*, Case when current='Y' then (case when start_date='20190101' then 'NEW' else 'Is' end) else 'Gone' end as status
from DataSource A
join (
select A.ID from IDsOfInterest A join DataSource B on A.ID=B.ID
where (current='Y' and start_date='20190101') or end_date='20190101'
group by a.id
) B on A.ID=B.ID
where (current='Y') or end_date='20190101'

per comment, sample data. Assume ID 1 exists in table IDsOfInterest:
Table DataSource:
ID, current, start_date, end_date, data, note
1, 'N', 20180101, 20180201, A, Disappears
1, 'N', 20180101, 20180201, B, Changes
1, 'Y', 20180201, 99991231, B, Changed
1, 'N', 20180101, 20190101, C, Recently Gone
1, 'Y', 20180101, 99991231, D, Always there
1, 'N', 20180101, 20190101, E, Recently Changes
1, 'Y', 20190101, 99991231, E, Recently Changed

Query results:
1, 'Y', 20180201, 99991231, B, Changed, Is
1, 'N', 20180101, 20190101, C, Recently Gone, Gone
1, 'Y', 20180101, 99991231, D, Always there, Is
1, 'N', 20180101, 20190101, E, Recently Changes, Gone
1, 'Y', 20190101, 99991231, E, Recently Changed, NEW

1 Ответ

0 голосов
/ 07 февраля 2019

Если вы используете with, вы можете один раз запросить данные с помощью фильтров, в которых пункт

Код станет более понятным, и вы получите выигрыш в производительности, поскольку вместо двух проходов таблицы DataSource вычитаем один раз.

with A as (
  select * from DataSource 
   where (current='Y' and start_date='20190101') or end_date='20190101'))
select A.*, Case when current='Y' then (case when start_date='20190101' 
               then 'NEW' else 'Is' end) else 'Gone' end as status
  from A
  join (
select I.ID from IDsOfInterest I join A on I.ID=A.ID
 group by a.id 
) B on A.ID=B.ID
where current='Y' or end_date='20190101'

Мы также можем переместить ваше объединение, чтобы получить идентификаторы в фильтре, и это будет быстрее, чем объединение

with A as (
  select * from DataSource 
   where (current='Y' and start_date='20190101') or end_date='20190101'))
select A.*, Case when current='Y' then (case when start_date='20190101' 
               then 'NEW' else 'Is' end) else 'Gone' end as status
 from A
where current='Y' or end_date='20190101'
  and ID in (select distinct I.ID from IDsOfInterest I join A on I.ID=A.ID) 

Пожалуйста, дайте мне знать, если это поможет

...