1

给定一个名为 Answers 的(简化)表,例如

Id  Person      Answer      Priority
1   Tom         France      Low       
2   Tom         Germany     High      
3   Fred        England     Low       
4   Amy         Italy       High      

我想编写一个 SQL 查询,每人返回一行,表示他们的最高优先级答案。我的想法是使用自加入

SELECT *
FROM Answers aLow
LEFT OUTER JOIN Answers aHigh 
    ON aLow.Person = aHigh.Person 
       AND aLow.Priority = 'Low' 
       AND aHigh.Priority = 'High'

然后在代码中检查哪些优先级列是非空的,但这会为汤姆返回一个额外的行

Id  Person      Answer      Priority    Id      Person  Answer  Priority
1   Tom         France      Low         2       Tom     Germany High      
2   Tom         Germany     High        NULL    NULL    NULL    NULL
3   Fred        England     Low         NULL    NULL    NULL    NULL
4   Amy         Italy       High        NULL    NULL    NULL    NULL

使用这种方法,所需的输出将是

Id  Person      Answer      Priority    Id      Person  Answer  Priority
1   Tom         France      Low         2       Tom     Germany High      
3   Fred        England     Low         NULL    NULL    NULL    NULL
4   Amy         Italy       High        NULL    NULL    NULL    NULL

我确定我一定遗漏了一些简单的东西,但不能指望它。

我错过了什么?有没有更好的方法来解决这个问题?

4

4 回答 4

1

您可以将公用表表达式与ROW_NUMBER窗口函数一起使用:

WITH cte 
     AS (SELECT [id], 
                [person], 
                [answer], 
                [priority], 
                RN = Row_number() 
                       OVER ( 
                         partition BY person 
                         ORDER BY CASE WHEN priority = 'High' THEN 0 ELSE 1 END 
                       ASC) 
         FROM   dbo.answers) 
SELECT [id], 
       [person], 
       [answer], 
       [priority] 
FROM   cte 
WHERE  rn = 1 

演示

ID  PERSON  ANSWER   PRIORITY
4   Amy     Italy    High
3   Fred    England  Low
2   Tom     Germany  High

排名功能

于 2013-06-14T23:02:38.617 回答
1

这是一种方法:

with priorityRank as
(
  select *
    , priorityRank = row_number() over (partition by Person
        order by case Priority when 'High' then 1 when 'Low' then 2 end
          , Id)
  from
  Answers
)
select Id
  , Person
  , Answer
  , Priority
from priorityRank
where priorityRank = 1

SQL Fiddle 与演示

于 2013-06-14T23:03:39.357 回答
0

您是否尝试过使用 DISTINCT,例如:

SELECT DISTINCT id, Person,Answer, Priority
FROM Answers aLow
LEFT OUTER JOIN Answers aHigh 
ON aLow.Person = aHigh.Person 
   AND aLow.Priority = 'Low' 
   AND aHigh.Priority = 'High'
于 2013-06-14T23:03:30.840 回答
0

如果我对您的理解正确,您应该从

SELECT *
FROM (SELECT * FROM Answers WHERE Priority = 'Low') aLow
FULL JOIN (SELECT * FROM Answers WHERE Priority = 'High') aHigh 
    ON aLow.Person = aHigh.Person 
于 2013-06-14T23:05:35.867 回答