ada*_*m.g 2 sql-server t-sql union
我看到有人交换了下面的代码:
SELECT
PK1
, PK2
, PK3
, PK4
, C
, B
, SUM(NUMERIC_1)
, SUM(NUMERIC_2)
, MAX(NUMERIC_3)
, SUM(NUMERIC_4)
FROM MATDOC_EXTRACT
WHERE A = ''
AND (
(
(
B = ''
OR B = 'K'
)
AND (
C = '01'
OR C = '02'
OR C = '07'
OR C = '08'
)
)
OR (
B = ''
AND (
C = '03'
OR C = '04'
)
)
)
GROUP BY PK1
, PK2
, PK3
, PK4
, C
, B;
Run Code Online (Sandbox Code Playgroud)
对于这个
SELECT
PK1
, PK2
, PK3
, PK4
, C
, B
, SUM(NUMERIC_1)
, SUM(NUMERIC_2)
, MAX(NUMERIC_3)
, SUM(NUMERIC_4)
FROM sap.MATDOC_EXTRACT
WHERE A = N''
AND B = N''
AND C IN (N'01', N'02', N'07', N'08', N'03', N'04')
GROUP BY PK1
, PK2
, PK3
, PK4
, C
, B
UNION ALL
SELECT
PK1
, PK2
, PK3
, PK4
, C
, B
, SUM(NUMERIC_1)
, SUM(NUMERIC_2)
, MAX(NUMERIC_3)
, SUM(NUMERIC_4)
FROM sap.MATDOC_EXTRACT
WHERE A = N''
AND B = N'K'
AND C IN (N'01', N'02', N'07', N'08')
GROUP BY PK1
, PK2
, PK3
, PK4
, C
, B;
Run Code Online (Sandbox Code Playgroud)
他们平等吗?
一个潜在的重要区别是,在第二种情况下,文字是nvarchar
,而在第一种情况下,文字是varchar
。
然而忽略这一方面......
是的
SELECT *
FROM TABLE
WHERE predicate_a
OR predicate_b
Run Code Online (Sandbox Code Playgroud)
可以重写为
SELECT *
FROM TABLE
WHERE predicate_a
UNION ALL
SELECT *
FROM TABLE
WHERE predicate_b
Run Code Online (Sandbox Code Playgroud)
只要predicate_a
和predicate_b
是互斥的。
predicate_a
否则,与两者匹配的行将predicate_b
错误地返回两次。
UNION ALL
在这种情况下,由于has的两个分支predicate_a
包含B = N''
并且predicate_b
包含B = N'K'
,则满足此条件。
在您的情况下,您有 10 个不同的等式谓词A, B, C
- 因此,如果您有一个索引,其中这些列按某种顺序排列,那么它可能可以通过十个搜索谓词来解决。
A | 乙 | C |
---|---|---|
'' | '' | 01 |
'' | '' | 02 |
'' | '' | 07 |
'' | '' | 08 |
'' | K | 01 |
'' | K | 02 |
'' | K | 07 |
'' | K | 08 |
'' | '' | 03 |
'' | '' | 04 |
当使用 编写的查询没有给出所需的索引查找或具有其他不需要的方面时,重写OR
as有时可能是一种有用的技术。UNION ALL
OR
如果我尝试
CREATE TABLE T1(A VARCHAR(1), B VARCHAR(1), C VARCHAR(2), INDEX IX (A, B, C))
UPDATE STATISTICS T1 WITH ROWCOUNT = 50000000, PAGECOUNT = 500000
UPDATE STATISTICS T1 IX WITH ROWCOUNT = 50000000, PAGECOUNT = 500000
SELECT *
FROM T1
WHERE A = ''
AND (
(
(
B = ''
OR B = 'K'
)
AND (
C = '01'
OR C = '02'
OR C = '07'
OR C = '08'
)
)
OR (
B = ''
AND (
C = '03'
OR C = '04'
)
)
)
Run Code Online (Sandbox Code Playgroud)
然后执行计划看起来像
执行计划本质上将其分解为两个单独的索引查找运算符,并将UNION ALL
它们组合在一起
|--Sort(DISTINCT ORDER BY:([Bmk1000] ASC))
|--Concatenation
|--Index Seek(OBJECT:([tempdb].[dbo].[T1].[IX]), SEEK:(
[tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='' AND [tempdb].[dbo].[T1].[C]='01'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='' AND [tempdb].[dbo].[T1].[C]='02'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='' AND [tempdb].[dbo].[T1].[C]='07'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='' AND [tempdb].[dbo].[T1].[C]='08'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='K' AND [tempdb].[dbo].[T1].[C]='01'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='K' AND [tempdb].[dbo].[T1].[C]='02'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='K' AND [tempdb].[dbo].[T1].[C]='07'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='K' AND [tempdb].[dbo].[T1].[C]='08') ORDERED FORWARD)
|--Index Seek(OBJECT:([tempdb].[dbo].[T1].[IX]), SEEK:(
[tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='' AND [tempdb].[dbo].[T1].[C]='03'
OR [tempdb].[dbo].[T1].[A]='' AND [tempdb].[dbo].[T1].[B]='' AND [tempdb].[dbo].[T1].[C]='04') ORDERED FORWARD)
Run Code Online (Sandbox Code Playgroud)
在两个搜索运算符之间,完整的 10 个索引搜索范围被扩展。
由于某种原因,它似乎没有看到它们不重叠,但是有一个删除重复项的步骤。
UNION ALL
在这种情况下,重写确实避免了这种情况
SELECT *
FROM T1
WHERE A = ''
AND B = ''
AND C IN ('01', '02', '07', '08', '03', '04')
UNION ALL
SELECT *
FROM T1
WHERE A = ''
AND B = 'K'
AND C IN ('01', '02', '07', '08')
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
261 次 |
最近记录: |