JOIN 中的 Sql 查询优化问题
Posted
技术标签:
【中文标题】JOIN 中的 Sql 查询优化问题【英文标题】:Sql Query optimization Issue in JOIN 【发布时间】:2016-06-28 07:20:28 【问题描述】:我在一个查询中有多个JOIN
语句,我必须检查JOIN
中的两个设置。如何以最好的方式做到这一点?
table: WebSettings
-------------------------------------------------------
Name | Setting | InstID | WebSettingID
-------------------------------------------------------
'EnableError' | 2 | 1111 | 1
'ErrorsSetting' | 0 | 2121 | 2
Index :
InstID
WebSettingID (InstID)
table: InstProd
-------------------------------------------------------
InstitutionID | Name
-------------------------------------------------------
1111 | 'Bank of Ind'
2121 | 'IOB'
Index :
InstitutionID
SELECT
Column1,
DATEADD(.....)
FROM
dbo.InstProd I
INNER JOIN dbo.WebSettings WS1 ON
WS1.InstitutionID = I.InstID AND
WS1.Name = 'EnableError' AND WS1.Setting=2
INNER JOIN dbo.WebSettings WS2 ON
WS2.InstitutionID = I.InstID AND
WS2.Name = 'ErrorsSetting' AND WS2.Setting=0
WHERE.....
我想在JOIN
中检查一个WebSettings = 2
和other = 0
有没有最好的解决方案?
【问题讨论】:
请更好地解释您的要求。你想要什么输出? 添加表定义和索引! 该代码甚至不会运行。您的代码中缺少 AND/OR 子句。 @Keppy:解释你的目标。我不知道您的选择 (JOIN) 是否最好。但是你必须发布你的表格结构和你想要的结果 @JoeTaras 添加了更多信息。 【参考方案1】:您可以决定不使用JOIN
,作为我的以下解决方案
如果你想要所有 InstProd
和 EnableError = 2
和 ErrorSettings = 0
试试这个:
SELECT I.*
FROM InstProd I
WHERE EXISTS
(SELECT 'EnableError = 2'
FROM WebSettings WS
WHERE WS.InstID = I.InstitutionID
AND WS.Name = 'EnableError' AND WS.Setting = 2)
AND EXISTS
(SELECT 'EnableError = 2'
FROM WebSettings WS
WHERE WS.InstID = I.InstitutionID
AND WS.Name = 'ErrorSettings' AND WS.Setting = 0)
如果您希望所有InstProd
都检查两个设置值
试试这个:
SELECT I.*,
CASE
WHEN
(SELECT COUNT(1)
FROM WebSettings WS
WHERE WS.InstID = I.InstitutionID
AND WS.Name = 'EnableError' AND WS.Setting = 2) > 0
AND
(SELECT COUNT(1)
FROM WebSettings WS
WHERE WS.InstID = I.InstitutionID
AND WS.Name = 'ErrorSettings' AND WS.Setting = 0) > 0
THEN 'OK'
ELSE 'KO'
END
FROM InstProd I
【讨论】:
谢谢。从性能的角度来看,您会建议哪一个?如果我的记录数很高,加入还是存在? 我认为不存在适用于所有情况的命令。取决于你想要什么,在这种情况下存在子句对于第一种情况是可以的(因为你不显示这些信息但你只用于条件),对于第二种情况我更喜欢(因为只有两个字段)选择中的子查询字段列表。使用 JOIN,您必须应用 group by 或 distinct 子句来丢弃重复的行【参考方案2】:是的,你不需要加入WebSettings
两次,虽然你没有发布你预期的输出,所以我不知道具体该怎么做,但是调整一下:
SELECT <column1>,<column2>,
MAX(CASE WHEN ws.Name = 'EnableError' AND ws.settings = 2 THEN <YourDesiredColumn> END) as enable_column,
MAX(CASE WHEN ws.Name = 'ErrorsSetting' AND ws.settings = 0 THEN <YourDesiredColumn2> END) as Errors_column
FROM bo.InstProd I
INNER JOIN dbo.WebSettings WS1 ON
WS1.InstitutionID = I.InstID AND
(WS.Name,ws.setting) in (('EnableError',2),('ErrorsSetting',0))
GROUP BY <column1>,<column2>
这将使您在同一行中同时启用和错误列,就像您的查询一样。
【讨论】:
我会在验证后回到这个。谢谢 我已经尝试过了,与我的脚本相比,性能没有任何改善,因此决定使用我的脚本。感谢您的支持。【参考方案3】:如果您不使用WS2
,最小化JOINS
可能会得到您所期望的结果
SELECT
Column1,
DATEADD(.....)
FROM
dbo.InstProd I
INNER JOIN dbo.WebSettings WS1 ON WS1.InstitutionID = I.InstID
AND ( WS1.Name = 'EnableError'
AND WS1.Setting = 2 )
OR ( WS1.Name = 'ErrorsSetting'
AND WS1.Setting = 0)
WHERE.....
【讨论】:
我会在验证后回到这个。谢谢 我已经尝试过了,与我的脚本相比,性能没有任何改善,因此决定使用我的脚本。感谢您的支持。以上是关于JOIN 中的 Sql 查询优化问题的主要内容,如果未能解决你的问题,请参考以下文章
Oracle SQL - FROM 子句中的 JOIN 顺序会影响性能优化吗?