我搜索并看过其他类似的问题,但没有任何帮助我。
以下表格的示例:
dbo.Product
PRODUCTID | LEVEL | SOMEFIELD1 | SOMEFIELD2
500 01 Blue Large
450 102 Black Large
....
250 03 Orange Medium
dbo.Level
LEVEL | ProductID
01 500
102 450
104 400
02 350
101 300
03 250
dbo.LevelMap
LEVEL1 | LEVEL2
01 101
01 102
01 103
02 104
02 105
02 106
我现在的加入非常缓慢,因为我这样做:
SELECT
p1.ProductID
lm1.Level1,
lm1.Level2,
... -- other fields from other tables here
FROM
dbo.Product p1,
INNER JOIN
dbo.Level l1 ON
l1.ProductID = p1.ProductID
LEFT JOIN dbo.LevelMap lm1
ON (l1.Level = lm1.Level1 OR
l1.Level = lm1.Level2)
我使用OR语句加入dbo.LevelMap lm1
两次。我想避免使用UNION,因为实际的SQL代码很大,我发现很难维护两组代码(每个联合一个代码)。
我想要做的就是返回给定Level1
的所有Level2
和Level
。 dbo.Level
表包含Level1和Level2值的混合,因此我需要连接两次到dbo.LevelMap
表。以下是传递ProductID值400
时理想结果集的样子:
PRODUCTID | LEVEL1 | LEVEL2
400 02 104
在JOIN中,它看到值104,在LEVEL2列上匹配它,然后获得相应的LEVEL1值。
问题是由于联接中的OR
,这种情况运行得非常慢。这些表有数千条记录可供匹配。
答案 0 :(得分:1)
听起来你正在寻找的是:
"查找LevelMap.Level1或LevelMap.Level2"
列中存在104的位置如果是这种情况,那么您可以执行以下操作:
SELECT *
FROM LevelMap map
WHERE map.Level1 = '104' OR map.Level2 = '104'
如果从LevelMap返回正确的结果,您只需加入Level表一次。
选项#2,加入两次并获取所需内容:
SELECT l1.Column1, l2.Column2
FROM LevelMap map
INNER JOIN Level l1 ON (map.Level1 = l1.Level)
INNER JOIN Level l2 ON (map.Level2 = l2.Level)
WHERE map.Level1 = '104' OR map.Level2 = '104'
关于这一点的好处是你正在做两个内连接。
答案 1 :(得分:1)
左边的连接对我来说毫无意义,因为l1甚至没有返回
当一个OR进入循环时,OR通常非常难 首先在这些列上放置索引
我刚看到情况
就像我说左边没有目的(我可以看到)
SELECT
lm1.Level1,
lm1.Level2
FROM
dbo.Level l1
JOIN dbo.LevelMap lm1
ON l1.Level = 104
AND ( l1.Level = lm1.Level1
OR l1.Level = lm1.Level2 )
我打赌你用这个来获得更好的表现 所以你必须维护单独的查询
SELECT
lm1.Level1,
lm1.Level2
FROM
dbo.Level l1
JOIN dbo.LevelMap lm1
ON l1.Level = 104
AND l1.Level = lm1.Level1
UNION
SELECT
lm1.Level1,
lm1.Level2
FROM
dbo.Level l1
JOIN dbo.LevelMap lm1
ON l1.Level = 104
AND l1.Level = lm1.Level2
这似乎不是3NF
我怀疑您的查询问题是错误数据设计的产物