如何避免两个相似的 CTE 定义
How to avoid two similar CTE definitions
我有一份报告使用了十几个 CTE 并且执行时间非常长。问题是很多 CTE 使用相同的 tables,以相同的方式加入,但条件不同,具体取决于列:
WITH
Kps_CTE (sp_id,ksd_ma_s) As
(
select wir_sp_id,SUM(ksd_ma)
from ksd
inner join ks on ksd_ks_id=ks_id
inner join do ON ksd_do_id=do_id AND do_dot_id in (101)
inner join wi ON do_wi_id=wi_id
inner join wir ON wir_wi_id=wi_id
INNER JOIN sp ON wir_sp_id=sp_id
where ksd_ksk_id=13
AND sp_date >= '2013-01-01'
group by wir_sp_id
),
Kis_CTE (sp_id,ksd_wn_s) As
(
select wir_sp_id,SUM(ksd_wn)
from ksd
inner join ks on ksd_ks_id=ks_id
inner join do ON ksd_do_id=do_id AND do_dot_id in (4)
inner join wi ON do_wi_id=wi_id
inner join wir ON wir_wi_id=wi_id
INNER JOIN sp ON wir_sp_id=sp_id
where ksd_ksk_id=14
AND sp_date>= '2013-01-01'
group by wir_sp_id
)
select * from ...
所以现在每个 table 我只得到两列。我想避免再次加入相同的 table 并使用不同的条件在一个 CTE 中创建几列。这可能吗?如果我只加入这两个我不会节省多少资源。
你必须描述你用这些 CTE 做什么。也许这可以弄清楚你的情况:
;WITH Kps_CTE (sp_id,ksd_ma_s) As
(
select wir_sp_id,
SUM(case when ksd_ksk_id=13 then ksd_ma end) as KPS,
Sum(case when ksd_ksk_id=14 then ksd_wn end) as KIS,
from ksd
inner join ks on ksd_ks_id=ks_id
inner join do ON ksd_do_id=do_id
inner join wi ON do_wi_id=wi_id
inner join wir ON wir_wi_id=wi_id
INNER JOIN sp ON wir_sp_id=sp_id
where (ksd_ksk_id=13 AND do_dot_id = 101
OR ksd_ksk_id=14 and do_dot_id = 4)
AND sp_date >= '2013-01-01'
group by wir_sp_id
),
如果 OR
列表很大 - 可以将其转换为另一个包含元组列表 (ksd_ksk_id; do_dot_id)
的 CTE,然后加入。
不确定您为什么在查询中使用所有这些幻数,如果我们最终发现您确实需要 PIVOT
或其他东西,请不要感到惊讶。
我有一份报告使用了十几个 CTE 并且执行时间非常长。问题是很多 CTE 使用相同的 tables,以相同的方式加入,但条件不同,具体取决于列:
WITH
Kps_CTE (sp_id,ksd_ma_s) As
(
select wir_sp_id,SUM(ksd_ma)
from ksd
inner join ks on ksd_ks_id=ks_id
inner join do ON ksd_do_id=do_id AND do_dot_id in (101)
inner join wi ON do_wi_id=wi_id
inner join wir ON wir_wi_id=wi_id
INNER JOIN sp ON wir_sp_id=sp_id
where ksd_ksk_id=13
AND sp_date >= '2013-01-01'
group by wir_sp_id
),
Kis_CTE (sp_id,ksd_wn_s) As
(
select wir_sp_id,SUM(ksd_wn)
from ksd
inner join ks on ksd_ks_id=ks_id
inner join do ON ksd_do_id=do_id AND do_dot_id in (4)
inner join wi ON do_wi_id=wi_id
inner join wir ON wir_wi_id=wi_id
INNER JOIN sp ON wir_sp_id=sp_id
where ksd_ksk_id=14
AND sp_date>= '2013-01-01'
group by wir_sp_id
)
select * from ...
所以现在每个 table 我只得到两列。我想避免再次加入相同的 table 并使用不同的条件在一个 CTE 中创建几列。这可能吗?如果我只加入这两个我不会节省多少资源。
你必须描述你用这些 CTE 做什么。也许这可以弄清楚你的情况:
;WITH Kps_CTE (sp_id,ksd_ma_s) As
(
select wir_sp_id,
SUM(case when ksd_ksk_id=13 then ksd_ma end) as KPS,
Sum(case when ksd_ksk_id=14 then ksd_wn end) as KIS,
from ksd
inner join ks on ksd_ks_id=ks_id
inner join do ON ksd_do_id=do_id
inner join wi ON do_wi_id=wi_id
inner join wir ON wir_wi_id=wi_id
INNER JOIN sp ON wir_sp_id=sp_id
where (ksd_ksk_id=13 AND do_dot_id = 101
OR ksd_ksk_id=14 and do_dot_id = 4)
AND sp_date >= '2013-01-01'
group by wir_sp_id
),
如果 OR
列表很大 - 可以将其转换为另一个包含元组列表 (ksd_ksk_id; do_dot_id)
的 CTE,然后加入。
不确定您为什么在查询中使用所有这些幻数,如果我们最终发现您确实需要 PIVOT
或其他东西,请不要感到惊讶。