我有三个 CTE,所有三个都使用相同的源表 table1 和相同的连接条件。 我想将所有三个合并为一个 CTE 以实现性能并有效地获得结果集。
如何在不影响结果集的情况下做到这一点。 它们之间唯一的区别是 WHERE 子句我想合并那个 WHERE 子句,使整个 CTE 成为一个
a AS (
select
ta.document,
case when users.ename is null
then ta.recipient
else concat(users.ename, '[', ta.recipient, ']') end as email_to
from schema1.table1 ta
left join users on ta.recipient = users.LDAP_id
where ta.action like 'X'
and ta.recipient not like ' '
and ta.document in (select document from head)
),
b AS (
select
ta.document,
isnull(
string_agg (
case when users.ename is null
then ta.recipient
else concat(users.ename,' [', ta.recipient, ']') end,
'; '
),
''
) as copy_to
from schema1.table1 ta
left join users on ta.recipient = users.LDAP_id
where ta.usr_flag like 'X'
and ta.document in (select document from head)
group by
ta.document
),
c AS (
select
ta.document,
isnull(
case when users.ename is null
then ta.recipient
else concat(users.ename, concat(users.ename,' [', ta.recipient, ']') end,
""
) as reserved_by
from schema1.table1 ta
left join users on ta.recipient = users.LDAP_id
where ta.reserved like 'X'
and ta.document in (select document from head)
)
我试图将这些列纳入一个选择,但我知道如何应用过滤器
您提出的重构可能不是获得良好查询效率所必需的。查询规划器在优化复杂查询方面做得非常好。它知道如何使用 CTE 将您的整体查询转换为抽象数据流树,然后优化这些数据流以使用适当的索引。您可以将(非递归)CTE 视为编写嵌套查询的简单语法——这就是查询规划器对待它们的方式。
最好避免重构:你所拥有的已经过测试并且可以工作。
重构查询仍有可能有所帮助。但是还有其他事情你应该先做。
添加适当的索引。如果您使用 SSMS——Microsoft 的 SQL Server Management Studio——这个提示适合您:在查询窗口中右键单击,然后选择显示实际执行计划,然后运行查询。执行计划显示有时会建议创建一个新索引。
创建那个索引,然后再次尝试实际执行计划,看看它是否提出了另一个建立在第一个建议之上的建议。通常 SSMS 建议的索引可以解决您的性能问题。如果不是...
阅读此然后提出一个具体问题,以寻求有关您实际执行计划的帮助。
该分析可能会引导您重构查询。
综上所述,您可以通过合并两个 CTE 的 SELECT 子句来组合
a
和 c
。 b
是聚合(GROUP BY)查询,因此不能与其他查询合并。它的结果集固有地具有不同的行数,因此除非您知道它将如何连接到其他表,否则您无法开始合并它。
不清楚你想如何合并这些数据。假设您只想要一个
UNION ALL
,合并 a
和 c
非常容易,但是 b
更复杂,需要相当复杂的分组结构,并且可能不值得合并。
请注意,一些
case
表达式已被简化。
merged_a_and_b AS (
select
ta.document,
case when ta.action like 'X'
then isnull(
users.ename + '[' + ta.recipient + ']',
ta.recipient
)
end as email_to
case when ta.reserved not like 'X'
then isnull(
isnull(
users.ename + '[' + ta.recipient + ']',
ta.recipient
),
""
)
end as reserved_by
from schema1.table1 ta
left join users on ta.recipient = users.LDAP_id
where (
ta.action like 'X' and ta.recipient not like ' '
or ta.reserved like 'X'
)
and ta.document in (select document from head)
)
假设你想要更多的联合风格而不是联合,它会简单得多,特别是如果你可以按
ta.document
聚合所有行
merged AS (
select
ta.document,
string_agg(
case when ta.action like 'X' and ta.recipient not like ' '
then isnull(
users.ename + '[' + ta.recipient + ']',
ta.recipient
)
end,
'; '
) as email_to,
isnull(
string_agg (
case when users.ename is null and ta.usr_flag like 'X'
then ta.recipient
else concat(users.ename,' [', ta.recipient, ']') end,
'; '
),
''
) as copy_to,
case when ta.reserved like 'X'
then isnull(
string_agg(
isnull(
users.ename + users.ename + ' [' + ta.recipient + ']',
ta.recipient
),
''
)
)
end as reserved_by
from schema1.table1 ta
left join users on ta.recipient = users.LDAP_id
where ta.reserved like 'X'
where ta.document in (select document from head)
)