SQL优雅:是否可以避免此子选择?

时间:2019-02-06 17:09:51

标签: sql netezza

我有一条SQL语句,其中subselect where子句与外部where子句非常相似。这让我想知道是否有一种更简洁的表达方式。

数据每个月都会收到更新,每行数据在出现时都有一个开始日期,在不再出现时有一个结束日期。由于数据线完全消失或数据线完全更改,它可能不再出现。任何给定的ID可能包含1或多行数据。我的内部选择查找所有最近更改/删除过的行的所有ID,而外部选择查找所有具有当前或最近更改/删除过的ID的所有行。它正在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 :(得分:0)

如果使用with,则可以使用where子句中的过滤器查询数据一次。

代码更加简洁,您将获得性能上的好处,因为您无需在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'

我们还可以移动您的联接以将ID放入过滤器,这将比联接更快

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) 

请告诉我这是否有帮助