【问题标题】:Which is the best for this query, "Inner join" or "Where"哪个最适合这个查询,“内连接”或“哪里”
【发布时间】:2018-02-10 23:09:48
【问题描述】:

我有这个 SQL 查询

SELECT t.id AS taskid,
       STUFF(
           (
               SELECT ',' + x.tID
               FROM   (
                          SELECT CAST(id AS VARCHAR(200)) AS tid
                          FROM CRSTask c WHERE c.ParentTask = 
                          7562 -- comment this line
                      ) x
                      FOR XML PATH('')
           ),
           1,
           1,
           ''
       ) AS strIDS
FROM   CRSTask t
WHERE t.ParentTask IS NULL
AND t.id = 7562 -- comment this line  

这个查询的结果是:

 id          strIDS  
7562    7615,7616,7617,7618,7619,7620,7621,7631,7632,123

这很好,但是当我尝试用另一个表中的名称替换 strIDS 时,需要很长时间。

例如123 [strIDS 中的最后一个 id] 是来自 CRSTask 的 taskID,与 CRSTaskReceiver 具有一对一的关系 并且 taskReceiver 与 Portal_Users_View(id,userName) 具有一对一的关系 -我需要用等效的用户名替换 123 - 我使用 Joins 完成了它.. 它需要很多时间,也使用表之间的 Where 需要很多时间

【问题讨论】:

  • 您需要向我们展示您修改后的查询。以及您尝试加入的表的结构。
  • SELECT t.id AS taskid,STUFF( ( SELECT ',' + x.ArabicName FROM ( SELECT ArabicName FROM Portal_Users_View WHERE ID IN (SELECT CRSTaskReceiver.ReceiverID FROM CRSTaskReceiver WHERE CRSTaskReceiver.CRSTaskID IN /*305 */ (SELECT CAST(id AS VARCHAR(200)) AS tid FROM CRSTask c WHERE c.ParentTask = 7562 )) ) x FOR XML PATH('') ), 1, 1, '' ) AS strIDS FROM CRSTask t WHERE t.ParentTask 为空且 t.id = 7562
  • 编辑您的帖子,而不是在评论框中。

标签: sql tsql optimization


【解决方案1】:

回答您的问题:在我看来,JOIN 在 99% 的情况下更好,因为它们更清楚地显示了基础数据模型。这使得维护代码变得更容易,并且查询优化器也更容易提出一个体面的查询计划。

我不是 UDF 的忠实粉丝,但在这种情况下,它可能是解决问题的最简单方法,因为 MSSQL 本身不支持聚合字符串:

-- create User Defined Function to fetch list of names for given taskid
CREATE FUNCTION dbo.fn_names_from_taskid ( @taskid int )
RETURNS nvarchar(max)
AS
    BEGIN
        DECLARE @result nvarchar(max)
        SELECT @result = ''

        SELECT @result = @result 
                       +  Portal_Users_View.ArabicName + ','
          FROM Portal_Users_View 
          JOIN CRSTaskReceiver 
            ON CRSTaskReceiver.ReceiverID = Portal_Users_View.ID
          JOIN CRSTask c 
            ON CAST(c.id AS VARCHAR(200)) = CRSTaskReceiver.CRSTaskID -- cast really necessary?
           AND c.ParentTask = @taskid 

        -- strip last comma (if present)
        SELECT @result = (CASE WHEN Right(@result, 1) = ',' THEN Left(@result, Len(@result) - 1) ELSE @result END)

        Return(@result)
    END

GO

-- usage    
SELECT taskid    = t.id,
       nameslist = dbo.fn_names_from_taskid (t.id)
  INTO #test
 WHERE id = 7652

PS:我试图从上面的代码中解释你的数据模型,但你需要仔细检查它!

PS:Cast() 真的有必要吗?我会假设所有 id 字段都存储为 int ?!?如果是这样(并且使用正确的索引),这些连接应该“非常快”,但是使用 Cast() ,服务器无法正确使用其索引,并且您可能会遇到最奇怪的性能表现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-18
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多