OR语句SQL的优先级

时间:2013-08-13 20:26:33

标签: sql sql-server-2008

我有以下代码段:

WHERE (Person.WorkGroupId = 2 or Person.RoleId = 2)

我想要发生的是在Person表上返回第一次出现WorkGroupId为2的情况。但是,如果没有WorkgroupId为2的人,则在Person表中选择RoldId为2的第一个匹配项。

由于

3 个答案:

答案 0 :(得分:12)

SELECT TOP (1) * FROM 
(
  SELECT TOP (1) *, o = 1
  FROM Person
  WHERE WorkGroupId = 2 

  UNION ALL

  SELECT TOP (1) *, o = 2
  FROM Person 
  AND RoleId = 2
) AS x ORDER BY o;

答案 1 :(得分:7)

如果你只使用它,你会得到多条记录。

我会这样做: (有问题的表只扫描一次)

Select top 1 *
From dbo.SomeTable
where WorkGroupId=2 or RoleId=2
Order by case 
   when WorkGroupId=2 then 1 
   when RoleId=2 then 2 
end

答案 2 :(得分:3)

CREATE TABLE dbo.Person(
    PersonID INT IDENTITY(1,1) PRIMARY KEY,
    FullName NVARCHAR(100) NOT NULL,
    Col1 INT NOT NULL,
    WorkGroupId TINYINT NOT NULL,
    RoleId TINYINT NOT NULL,
    [Priority] AS CONVERT(TINYINT,              
                CASE  
                    WHEN WorkGroupId=2 THEN 1 -- Priority 1
                    WHEN RoleId=2 THEN 2        -- Priority 2
                    ELSE 3                      -- Priority 3
                END)
);
GO
-- http://technet.microsoft.com/en-us/library/ms189292.aspx
SET NUMERIC_ROUNDABORT OFF;
SET ANSI_NULLS ON;
SET ANSI_PADDING ON;
SET ANSI_WARNINGS ON;
SET ARITHABORT ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET QUOTED_IDENTIFIER ON;
GO
CREATE INDEX IX_Person_Col1_Priority
ON dbo.Person (Col1,[Priority])
INCLUDE (FullName);
GO
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'A'   ,1,1,1);
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'BB'  ,1,0,1);
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'CCC' ,1,2,1); -- <-- 
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'DDDD',1,0,0);
GO
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'X'  ,2,1,1);
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'YY' ,2,1,2); -- <-- 
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'ZZZ',2,1,3);
GO
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'?'   ,3,1,1);
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'!!'  ,3,2,1); -- <-- 
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'%%%' ,3,1,2); 
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'&&&&',3,1,3);
GO
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'-'   ,4,1,1); -- No result
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'--'  ,4,1,1); -- No result
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'---' ,4,1,1); -- No result
INSERT dbo.Person (FullName,Col1,WorkGroupId,RoleId) VALUES (N'----',4,1,1); -- No result
GO

SELECT *
FROM(
    SELECT  p.PersonID,p.FullName,
            -- If you have many persons with the same priority then you should use DENSE_RANK
            ROW_NUMBER() OVER (ORDER BY p.[Priority]) AS Rnk
    FROM    dbo.Person p
    WHERE   p.Col1=1
    AND     p.[Priority] IN (1,2)   
) x
WHERE x.Rnk=1;

SELECT *
FROM(
    SELECT  p.PersonID,p.FullName,
            -- If you have many persons with the same priority then you should use DENSE_RANK
            ROW_NUMBER() OVER (ORDER BY p.[Priority]) AS Rnk
    FROM    dbo.Person p
    WHERE   p.Col1=2
    AND     p.[Priority] IN (1,2)   
) x
WHERE x.Rnk=1;

SELECT *
FROM(
    SELECT  p.PersonID,p.FullName,
            -- If you have many persons with the same priority then you should use DENSE_RANK
            ROW_NUMBER() OVER (ORDER BY p.[Priority]) AS Rnk
    FROM    dbo.Person p
    WHERE   p.Col1=3
    AND     p.[Priority] IN (1,2)   
) x
WHERE x.Rnk=1;

SELECT *
FROM(
    SELECT  p.PersonID,p.FullName,
            -- If you have many persons with the same priority then you should use DENSE_RANK
            ROW_NUMBER() OVER (ORDER BY p.[Priority]) AS Rnk
    FROM    dbo.Person p
    WHERE   p.Col1=4 
    AND     p.[Priority] IN (1,2)
) x
WHERE x.Rnk=1;

结果:

PersonID FullName Rnk
-------- -------- ---
3        CCC      1


PersonID FullName Rnk
-------- -------- ---
6        YY       1


PersonID FullName Rnk
-------- -------- ---
9        !!       1


PersonID FullName Rnk
-------- -------- ---

最后四个陈述的执行计划是: enter image description here

注意:Col1代表测试编号。