【问题标题】:Sql Query optimization Issue in JOINJOIN 中的 Sql 查询优化问题
【发布时间】:2023-03-31 03:08:01
【问题描述】:

我在一个查询中有多个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 添加了更多信息。

标签: sql sql-server join query-optimization


【解决方案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.....

【讨论】:

  • 我会在验证后回到这个。谢谢
  • 我已经尝试过了,与我的脚本相比,性能没有任何改善,因此决定使用我的脚本。感谢您的支持。
猜你喜欢
  • 2019-03-30
  • 1970-01-01
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
  • 2017-06-08
  • 1970-01-01
相关资源
最近更新 更多