使用LEFT JOIN选择DISTINCT,在t-SQL中使用ORDERed BY

时间:2012-07-20 21:04:42

标签: sql sql-server tsql sql-order-by distinct

我在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)

选择相同类型的所有记录的ID,具有相同的dtIn日期,按stOut按升序排序:

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放在不同的地方,但这一切似乎都不起作用。我在这里做错了什么?

5 个答案:

答案 0 :(得分:6)

按照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

但现在,问题是:引擎如何按PersonName命令这两个值“Apple”和“Peach”? 哪个 PersonNames?每个水果有两个人!确切地说,应该使用哪个名称来确定ApplePeach是否优先?

相反,将您的查询重写为聚合:

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;

答案 1 :(得分:4)

当您缩小个人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的可能性。

答案 2 :(得分:0)

当您使用'DISTINCT'关键字时,您只能使用ORDER BY子句中的那些列作为select语句的一部分。所以你只能通过tbl.id

订购

如果ID是唯一的,则DISTINCT关键字没有任何意义,会导致性能下降,您只需将其删除即可。如果它们不是并且您决定在保持DISTINCT的同时选择tbl.dtOut,则对tbl.id和tbl.dtOut可以为您提供具有相同tbl.id的多个条目,这可能是不希望的。

检查this article 可能的解决方法和解释为什么禁止此类查询。

答案 3 :(得分:0)

您必须在选择列表中包含列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

答案 4 :(得分:0)

您遇到此错误是因为您没有将(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  

(有6行,因为它给出了id / date字段的明显组合)