1

次のようなAnswersという(簡略化された)テーブルが与えられた場合

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

最も優先度の高い回答を示す 1 行を 1 人につき 1 行返す SQL クエリを書きたいと思います。私の考えは、自己結合を使用することでした

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

次に、プライオリティ列がnullではないコードを調べますが、それはTomの余分な行を返します

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

これを行う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

demo を使用した SQL Fiddle

于 2013-06-14T23:03:39.357 に答える
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 に答える
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 に答える