SQL 优雅:这个子选择可以避免吗?
SQL elegance: Can this subselect be avoided?
我有一个 SQL 语句,其中子 select where 子句与外部 where 子句非常相似。这让我想知道是否有更简洁的表达方式。
数据每个月都会收到更新,每行数据在出现时都有一个开始日期,在不再出现时有一个结束日期。由于数据行完全消失或数据行根本改变,它可能不再出现。任何给定的 id 可能有 1 行或多行数据。我的内部 select 查找最近 changed/been 删除了任何行的所有 ID,外部 select 查找具有当前 ID 或最近 changed/been 删除的所有行.这是 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
如果您使用 with
,您可以使用 where 子句中的过滤器查询您的数据一次
代码更简洁,您将获得性能优势,因为您只读取一次数据源,而不是两次传递 table。
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)
如果有帮助请告诉我
我有一个 SQL 语句,其中子 select where 子句与外部 where 子句非常相似。这让我想知道是否有更简洁的表达方式。
数据每个月都会收到更新,每行数据在出现时都有一个开始日期,在不再出现时有一个结束日期。由于数据行完全消失或数据行根本改变,它可能不再出现。任何给定的 id 可能有 1 行或多行数据。我的内部 select 查找最近 changed/been 删除了任何行的所有 ID,外部 select 查找具有当前 ID 或最近 changed/been 删除的所有行.这是 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
如果您使用 with
,您可以使用 where 子句中的过滤器查询您的数据一次
代码更简洁,您将获得性能优势,因为您只读取一次数据源,而不是两次传递 table。
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)
如果有帮助请告诉我