web-dev-qa-db-ja.com

LEFT JOINを使用したSELECT DISTINCT、t-SQLでのORDER BY

SQL Server 2008には次の表があります。

CREATE TABLE tbl (ID INT, dtIn DATETIME2, dtOut DATETIME2, Type INT)

INSERT tbl VALUES
(1, '05:00', '6:00', 1),
(2, '05:00', '7:00', 1),
(3, '05:01', '8:00', 1),
(4, '05:00', '8:00', 1),
(5, '05:00', '6:00', 2),
(6, '05:00', '7:00', 2)

これは、stOutで昇順に並べられた、同じタイプの同じdtIn日付を持つすべてのレコードのIDを選択します。

SELECT DISTINCT tbl.id FROM tbl   
  LEFT JOIN tbl AS t1
  ON tbl.type = t1.type AND
     tbl.dtIn = t1.dtIn
  ORDER BY tbl.dtOut ASC

しかし、それは私にエラーを与えます:

SELECT DISTINCTが指定されている場合、ORDER BY項目は選択リストに表示される必要があります

そのORDER BYを別の場所に置いてみましたが、すべてが機能していないようです。ここで何が悪いのですか?

9
ahmd0

個々のIDを絞り込むと、各IDに複数のdtOutが関連付けられる可能性があります。その場合、SQL Serverはどの順序を使用するかをどのようにして知るのでしょうか。

あなたは試すことができます:

SELECT t1.id
FROM tbl t1
LEFT JOIN  tbl t2 on t1.type = t2.type AND t1.dtIn = t2.dtIn
GROUP BY t1.id, t2.dtOut
ORDER BY t2.dtOut

ただし、前述のように、右側のテーブルの複数のレコードと一致する場合、同じIDが複数回リストされる可能性があります。

5
Joel Coehoorn

DISTINCTアイテムのリストに含まれていない列によるORDERには意味がありません。

簡単なシナリオを使用してみましょう。まず、テーブルFruitPerson

Fruit  PersonName
-----  ------
Apple  Joe
Apple  Mary
Peach  Karen
Peach  Lance

これはあなたがやろうとしていることと同等のクエリです:

SELECT DISTINCT Fruit
FROM FruitPerson
ORDER BY PersonName;

ORDER BYなしのこのクエリの結果は次のとおりです。

Fruit
-----
Apple
Peach

しかし今、問題は、エンジンがこれらの2つの値 "Apple"と "Peach"をPersonNameでどのように並べるべきかということです。 どちら PersonNames?果物ごとに2人です! AppleまたはPeachが最初に来るかどうかを決定するために、正確にどの名前を使用する必要がありますか?

代わりに、クエリを集計として書き換えます。

SELECT Fruit, MinName = Min(PersonName) -- which name to order on
FROM FruitPerson
GROUP BY Fruit -- here's how you get your distinctness
ORDER BY MinName;
6
ErikE

選択リストに(tbl.dtOut)を指定しなかったため、このエラーが発生していました。

SELECT DISTINCT tbl.dtOut FROM tbl    
  LEFT JOIN tbl AS t1  
  ON tbl.type = t1.type AND  
     tbl.dtIn = t1.dtIn  
  ORDER BY tbl.dtOut ASC

結果セット(3行)を取得し、idフィールドも必要な場合

SELECT DISTINCT tbl.dtOut, tbl.ID FROM tbl      
  LEFT JOIN tbl AS t1  
  ON tbl.type = t1.type AND  
     tbl.dtIn = t1.dtIn  
  ORDER BY tbl.dtOut ASC  

(ID /日付フィールドの明確な組み合わせを提供するため、6つの行があります)

0
NG.

「DISTINCT」キーワードを使用する場合、selectステートメントの一部であるORDER BY句でこれらの列のみを使用できます。したがって、tbl.idでのみ注文できます

IDが一意の場合、DISTINCTキーワードは意味がなく、パフォーマンスが低下するため、削除するだけです。そうでない場合に、DISTINCTを維持したままtbl.dtOutも選択することを決定した場合、tbl.idとtbl.dtOutのペアは、おそらく望ましくない同じtbl.idを持つ複数のエントリを提供する可能性があります。

可能な回避策とそのようなクエリが禁止されている理由の説明については、 この記事 を確認してください。

0
Andy

列tbl.dtOutを選択リストに含めて、何を注文するかがわかるようにする必要があります。

SELECT DISTINCT tbl.id, tbl.dtOut FROM tbl   
  LEFT JOIN tbl AS t1
  ON tbl.type = t1.type AND
     tbl.dtIn = t1.dtIn
  ORDER BY tbl.dtOut ASC
0
specman