我如何避免WHERE子句中的函数USER_ID()

时间:2013-06-13 07:35:25

标签: sql-server where clause

我正在尝试像这样优化查询:

SELECT  id, type, parent_id
FROM    [dbo].[v5] with(nolock)
WHERE 
(
    USER_ID() = 1
    OR
        (
            v5.type IN (1,2,3)
            and 
            EXISTS
            (
                    SELECT obj_id FROM dbo.access with(nolock) 
                    where  access.obj_id = id 
                    AND obj_id.[u_name] in 
                    (
                        select SUSER_SNAME() union all 
                        select [name] COLLATE database_default from dbo.u_role
                    )
            )
        )
)

它的工作时间为25秒。当我评论这一行时:

--USER_ID() = 1
 --     OR

它的工作时间为5秒。如何优化这个查询?如何避免在where子句中使用USER_ID()?

1 个答案:

答案 0 :(得分:1)

试试这个 -

变体#1:

DECLARE @user INT
SELECT @user = USER_ID() --<--

SELECT 
      v.id
    , v.[type]
    , v.parent_id
FROM dbo.v5 v WITH (NOLOCK)
LEFT JOIN (
    SELECT DISTINCT a.obj_id 
    FROM dbo.access a WITH(NOLOCK) 
    WHERE a.[u_name] IN 
        (
            SELECT SUSER_SNAME() 
            UNION ALL 
            SELECT [name] COLLATE database_default 
            FROM dbo.u_role
        )
) a ON a.obj_id = v.id 
WHERE @user = 1
    OR (
            v5.[type] IN (1, 2, 3) 
        AND 
            a.obj_id IS NOT NULL
    )

变体#2:

IF USER_ID() = 1 BEGIN

    SELECT 
          v.id
        , v.[type]
        , v.parent_id
    FROM dbo.v5 v WITH (NOLOCK)

END
ELSE BEGIN

    SELECT 
          v.id
        , v.[type]
        , v.parent_id
    FROM dbo.v5 v WITH (NOLOCK)
    JOIN (
        SELECT DISTINCT a.obj_id 
        FROM dbo.access a WITH(NOLOCK) 
        WHERE a.[u_name] IN 
            (
                SELECT SUSER_SNAME() 
                UNION ALL 
                SELECT [name] COLLATE database_default 
                FROM dbo.u_role
            )
    ) a ON a.obj_id = v.id 
    WHERE v5.[type] IN (1, 2, 3) 

END

变体#3:

DECLARE @user INT
SELECT @user = USER_ID()

SELECT  id, [type], parent_id
FROM [dbo].[v5] WITH(NOLOCK)
WHERE @user = 1
    OR (
        v5.[type] IN (1,2,3)
        AND 
        EXISTS (
            SELECT 1 
            FROM dbo.access WITH(NOLOCK) 
            WHERE access.obj_id = id 
                AND access.[u_name] IN 
                    (
                        SELECT SUSER_SNAME() 
                        UNION ALL 
                        SELECT [name] COLLATE database_default 
                        FROM dbo.u_role
                    )
        )
    )
OPTION (RECOMPILE)