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 = 2other = 0

有没有最好的解决方案?

【问题讨论】:

请更好地解释您的要求。你想要什么输出? 添加表定义和索引! 该代码甚至不会运行。您的代码中缺少 AND/OR 子句。 @Keppy:解释你的目标。我不知道您的选择 (JOIN) 是否最好。但是你必须发布你的表格结构和你想要的结果 @JoeTaras 添加了更多信息。 【参考方案1】:

您可以决定不使用JOIN,作为我的以下解决方案

如果你想要所有 InstProdEnableError = 2ErrorSettings = 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 顺序会影响性能优化吗?

用户定义函数上的 Sql Join:如何优化

优化 MYSQL 中的 UPDATE JOIN 查询

使用 WHERE 子句中的过滤器优化 OUTER JOIN 查询。(查询规划器)

SQL查询优化JOIN多列

使用 JOIN 而不是 NOT IN 优化 SQL 查询