2016-04-07 18 views
3

我有,目前带来了数据这样的查询:在SQL Server中订购NULL结果有所不同?

ID | Name | Arrival | Departure 
----------------------------------- 
1 | John | NULL  | 2:30:00 
2 | John | NULL  | 11:00:00 
3 | John | NULL  | 14:00:00 
4 | John | 10:30:00 | 11:00:00 
5 | John | 12:00:00 | 13:00:00 

这是我做的事:order by Name, Arrival, Departure

不过,我想的却是以下几点:

  1. 如果到达条目NULL,然后行应该由 出发列排序。
  2. 如果到达条目NULL和 有与相同的出发数据多行,那么它 应该后下令有一个到达 进入其他行。

结果:

ID | Name | Arrival | Departure 
----------------------------------- 
1 | John | NULL  | 2:30:00 
4 | John | 10:30:00 | 11:00:00 
2 | John | NULL  | 11:00:00 
5 | John | 12:00:00 | 13:00:00 
3 | John | NULL  | 14:00:00 

编辑:对于那些谁认为这是一个重复的问题 - 原来的问题是不一样的,由于第二个条件。但是,由于我的数据结构(抵达时间总是在出发时间之前),因此同样的答案也适用。

编辑2:出发也可以为NULL。当出发为空时,到达条目是非空的。如果是这种情况,应该按到货顺序。如果两行都具有相同的到达条目,则NULL应该为非空值之前。注意,这与NULL到达条目(上面的条件2)相反,其中NULL在非空值之后。

+0

[条件ORDER BY取决于列值]的可能重复(http://stackoverflow.com/questions/7464434/conditional-order-by-depending-on-column-values) –

+0

第二条规则有点不清楚我。你的意思是说,如果到达第4排的时间是11:00:00,那么它应该总是排在一个空到达和11:00:00出发的行之前。 –

+0

@JoachimIsaksson我的意思是对于离开值相同的行,则具有空到达值的条目应该低于具有非空到达值的行。我提到它的原因是因为通常在非空值之前排序NULL。在上面的预期结果中,第4行位于第2行上方,因为它具有非空的到达值。 – painiyff

回答

3

DECLARE @tbl TABLE(ID INT,Name VARCHAR(100),Arrival TIME,Departure TIME); 
INSERT INTO @tbl VALUES 
(1,'John',NULL,'2:30:00') 
,(2,'John',NULL,'11:00:00') 
,(3,'John',NULL,'14:00:00') 
,(4,'John','10:30:00','11:00:00') 
,(5,'John','12:00:00','13:00:00'); 

SELECT * FROM @tbl 
ORDER BY Name,CASE WHEN Arrival IS NULL THEN Departure ELSE Arrival END 

结果

1 John NULL    02:30:00.0000000 
4 John 10:30:00.0000000 11:00:00.0000000 
2 John NULL    11:00:00.0000000 
5 John 12:00:00.0000000 13:00:00.0000000 
3 John NULL    14:00:00.0000000 

试试吧你不妨考虑一下ISNULL(),但你应该阅读有关“优化搜索”,特别是如果你处理很多行和索引...

+0

嗨下来的选民!不应该有没有评论的投票... – Shnugo

+0

这个答案的重复的副本? http://stackoverflow.com/a/7464492/1507566 –

+0

没有很多不同的方法来完成OP的目标,所以别人可能会得出同样的结论应该不会令人惊讶。 – dazedandconfused

0

你可以按照我认为的子句的顺序做case语句。

ISNULL将成为我的首选方式,因为它专门用于处理空值而且体积更小。

ORDER BY Name, ISNULL(Arival, Departure) 
+0

不,请阅读[this](http://stackoverflow.com/questions/799584/what-makes-a-sql-statement-sargable)和[this](http://stackoverflow.com/questions/5024090/ sargable-queries-using-isnull-in-tsql),顺便说一句:我不是下来的选民... – Shnugo

+0

是的。你的答案是比较完整的。 – Jrud

+0

所以,它不是可靠的。有用。 +1我怀疑表中有很多行。 – Paparazzi

0

为避免使用WHERE子句中的条件,您可以使用计算列来保留您的排序条件。此外,使用TIME型为到达和离开是更有效的(空间,比较等):

create table Data 
(
    ID INT NOT NULL, 
    Name VARCHAR(100) NOT NULL, 
    Arrival TIME NULL, 
    Departure TIME NULL, 
    ActualTime AS ISNULL(Arrival, Departure) PERSISTED 
) 
GO 

INSERT INTO Data (ID, Name, Arrival, Departure) 
VALUES 
(1,'John',NULL,'2:30:00') 
,(2,'John',NULL,'11:00:00') 
,(3,'John',NULL,'14:00:00') 
,(4,'John','10:30:00','11:00:00') 
,(5,'John','12:00:00','13:00:00'); 
GO 

select * from Data 
order by ActualTime 

基于其他查询,则还可以具有使用作为密钥的索引。

0

为了让空来最后我想你可以再补充

ORDER BY Name 
     , ISNULL(Arival, dateadd(ss, 1, Departure)) 
     , Departure 

,但如果你有到来是进入与空下一出发,那么你会得到一些也许不是理想的结果
你需要说明你到底如何想处理这一

如果你有

6 | John | 12:30:00 | 11:00:00 

你真的想那之后

5 | John | 12:00:00 | 13:00:00 

这将是一个更容易只是排序在离开第一

declare @bigdate datetime = cast('2099-01-01' as datetime); 
ORDER BY Name 
     , Departure 
     , ISNULL(Arival, @bigdate); 
1

如何简单ORDER没有条件表达式和功能。

如果您想先订购Departure,那么请先订购它。 如果您想通过Arrival接下来订购,但想要NULL最后,请使用DESC

这将正常工作,即使Arrival相同Departure,例如,如果Arrival是第4行,而不是10:30:0011:00:00

我想感谢@Shnugo提供测试数据的脚本。

DECLARE @tbl TABLE(ID INT,Name VARCHAR(100),Arrival TIME,Departure TIME); 
INSERT INTO @tbl VALUES 
(1,'John',NULL,'2:30:00') 
,(2,'John',NULL,'11:00:00') 
,(3,'John',NULL,'14:00:00') 
,(4,'John','10:30:00','11:00:00') 
,(5,'John','12:00:00','13:00:00'); 

SELECT * 
FROM @tbl 
ORDER BY 
    Name 
    ,Departure 
    ,Arrival DESC; 

结果

+----+------+------------------+------------------+ 
| ID | Name |  Arrival  | Departure  | 
+----+------+------------------+------------------+ 
| 1 | John | NULL    | 02:30:00.0000000 | 
| 4 | John | 10:30:00.0000000 | 11:00:00.0000000 | 
| 2 | John | NULL    | 11:00:00.0000000 | 
| 5 | John | 12:00:00.0000000 | 13:00:00.0000000 | 
| 3 | John | NULL    | 14:00:00.0000000 | 
+----+------+------------------+------------------+ 

...虽然目前尚不清楚是否有可能有多个行与非空Arrival和完全相同的Departure ...什么排序你想在这种情况下?

+0

不应该有多于一行的非null'Arrival'和相同的'Departure'。但是,我在OP中没有提到的一件事是'离开'也可以为空。如果它们为空,那么相应的'Arrival'非空。在这些情况下,它应该按'Arrival'命令。 – painiyff

+0

@painiyff,好吧,在这种情况下,你必须在'ORDER BY'中用'CASE'或'ISNULL'或'COALESCE'来表达一些表达式。 –