SELECT DISTINCT with LEFT JOIN, ORDERed BY in t-SQL

馋奶兔 提交于 2020-12-01 09:54:14

问题


I have the following table in 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)

that selects IDs of all records of the same type, with the same dtIn date, ordered by stOut in ascending order:

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

But it gives me an error:

ORDER BY items must appear in the select list if SELECT DISTINCT is specified

I tried putting that ORDER BY in different places and it all doesn't seem to work. What am I doing wrong here?


回答1:


When you narrow it down to individual id's, you create the possibility that each id might have more than one dtOut associated with it. When that happens, how will Sql Server know which order to use?

You could try:

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

However, as I mentioned above this can open the possibility of having the same id listed more than once, if it matches to more than one record on the right-side table.




回答2:


It doesn't make sense to ORDER by a column that is not included in the list of DISTINCT items.

Let's use a simple scenario. First, a table FruitPerson:

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

Here's the query equivalent to what you're trying to do:

SELECT DISTINCT Fruit
FROM FruitPerson
ORDER BY PersonName;

The result of this query without the ORDER BY is this:

Fruit
-----
Apple
Peach

But now, the question is: how should the engine order these two values "Apple" and "Peach" by PersonName? Which PersonNames? There are two people per fruit! Which name(s), exactly, should it use to decide whether Apple or Peach comes first?

Instead, rewrite your query as an aggregate:

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;



回答3:


You must include the column tbl.dtOut in your select list so it knows what to order on.

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



回答4:


You can use only those columns in ORDER BY clause which are part of your select statement when you use 'DISTINCT' key word. So you can order only by tbl.id

If ids are unique, DISTINCT keyword doesn't make any sense and will cause performance degradation and you can just remove it. In case they are not and you decide to select tbl.dtOut as well while keeping DISTINCT, the pair tbl.id and tbl.dtOut can give you multiple entries having same tbl.id which is probably not desired.

Check this article for possible workarounds and explanation why such queries are prohibited.




回答5:


You were having this error because you didnot put (tbl.dtOut) in the select list.

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

Will get you a result set (having 3 rows) and if you want the id field too then

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  

(having 6 rows, as it gives the distinct combination off id/date field)



来源:https://stackoverflow.com/questions/11586923/select-distinct-with-left-join-ordered-by-in-t-sql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!