SQL - 如何优化查询

时间:2012-03-12 12:24:16

标签: sql sql-server optimization

我编写了以下查询,该查询提取当前用户部门的子部门中的所有用户。 当前用户来自客户端应用程序,但我出于测试原因在SQL中对其进行了Decalred。

DECLARE @UserID INT = 72

SELECT * 
FROM users
WHERE Department_Id IN ( 
                        SELECT DISTINCT Id    /*, idp*/
                        FROM departments
                        WHERE idp IN (
                                        SELECT Department_Id 
                                        FROM users 
                                        WHERE Id = @UserID
                                        )
                        )

OR Department_Id IN (
                        SELECT DISTINCT idp
                        FROM departments
                        WHERE idp IN (
                                        SELECT Department_Id 
                                        FROM users 
                                        WHERE Id = @UserID
                                        )
                        )

我想从部门中选择 ID idp 来进行简短查询,但是当我使用这种方式时,它会返回给我SQL错误:

当子查询未与EXISTS一起引入时,只能在选择列表中指定一个表达式。

这是因为我的列表应该只包含一列,而不是2列。

请以任何方式建议我减少此查询,尤其是第二部分(在 OR 之后),这是第一部分的复制粘贴(在 OR 之前)

谢谢。

3 个答案:

答案 0 :(得分:3)

尝试使用EXISTS这样的

SELECT * 
FROM   users u
WHERE  EXISTS(  SELECT *
                FROM   departments
                WHERE  idp IN (SELECT Department_Id FROM users WHERE Id = @UserID)
                       AND (id = u.Department_Id
                           OR idp = u.Department_Id)    )

答案 1 :(得分:2)

一些想法......

  1. 嵌套的IN子查询不太友好。
  2. 使用IN
  3. 时不需要DISTINCT

    我会使用GROUP BY来处理1:很多关系,但是当你的答案是使用另一种结构时,我会尽量接近你所拥有的......

    DECLARE @UserID INT = 72
    
    SELECT
      *
    FROM
      users AS associates
    WHERE
      EXISTS (
        SELECT 
          *
        FROM
          users
        INNER JOIN      
          departments
            ON departments.idp = users.Department_Id
        WHERE
          users.id = @user_id
          AND (   departments.id  = associates.department_id
               OR departments.idp = associates.department_id)
      )
    

    如果您确实使用了GROUP BY方法,则可以避免所有子查询和相关子查询......

    DECLARE @UserID INT = 72
    
    SELECT
      associates.id
    FROM
      users
    INNER JOIN      
      departments
        ON departments.idp = users.Department_Id
    INNER JOIN
      users AS associates
        ON associates.department_id = departments.id
        OR associates.department_id = departments.idp
    WHERE
      users.id = @user_id
    GROUP BY
      associates.id
    

    如果您需要associates中的任何其他字段,只需将它们添加到SELECT GROUP BY。

答案 2 :(得分:1)

SELECT * 
FROM users
WHERE Department_Id IN ( 
                    SELECT myId FROM 
                     ( SELECT Id AS myId
                       FROM departments
                       UNION ALL
                       SELECT idp AS myId
                       FROM departments
                     ) A 
                    WHERE A.myId IN (
                                    SELECT Department_Id 
                                    FROM users 
                                    WHERE Id = @UserID
                                    )
                    )