Vas*_*kov 51 sql t-sql sql-server sorting min
我用SQL Server 2008 R2.
我需要按两列的最小值对表进行排序.
该表如下所示:
ID: integer;
Date1: datetime;
Date2: datetime.
Run Code Online (Sandbox Code Playgroud)
我希望我的数据按最少两个日期排序.
以这种方式对此表进行排序的最简单方法是什么?
Sta*_*vas 59
NOT NULL列.您需要在以下的ORDER BY子句中添加CASE语句:
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN Date1 < Date2 THEN Date1
ELSE Date2
END
Run Code Online (Sandbox Code Playgroud)
NULLABLE列.正如Zohar Peled在评论中写道,如果列可以为空,那么您可以使用ISNULL(但最好使用COALESCE而不是ISNULL,因为它是ANSI SQL standard)以下内容:
SELECT Id, Date1, Date2
FROM YourTable
ORDER BY CASE
WHEN COALESCE(Date1, '1753-01-01') < COALESCE(Date2, '1753-01-01') THEN Date1
ELSE Date2
END
Run Code Online (Sandbox Code Playgroud)
您可以在此处阅读有关ANSI标准日期格式的1753-01-01 信息.
jar*_*rlh 35
使用以下CASE表达式ORDER BY:
ORDER BY case when date1 < date2 then date1 else date2 end
Run Code Online (Sandbox Code Playgroud)
编辑:
如果需要考虑空值,请添加coalesce():
ORDER BY case when date1 < date2 then date1 else coalesce(date2,date1) end
Run Code Online (Sandbox Code Playgroud)
说明:
如果date1 <date2则按date1排序.(这里的两个日期都是非空的.)就像以前一样工作.
其他用于COALESCE()按date2(当date2不为null)或date1(当date2为null时)或null(如果两个日期都为null)进行排序.
最简单的方法是使用VALUES关键字,如下所示:
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY (SELECT MIN(v) FROM (VALUES (Date1), (Date2)) AS value(v))
Run Code Online (Sandbox Code Playgroud)
此代码适用于所有情况,即使是可以为空的列.
编辑:
使用COALESCE关键字的解决方案不是通用的.它有重要的限制:
Date类型(如果您使用之前的日期01/01/1753),它将无法工作NULL.它将NULL值解释
为最小值datetime.但它确实是真的吗?它不是偶数datetime,它什么都不是.IF如果我们使用两列以上,表达式会复杂得多.根据问题:
以这种方式对此表进行排序的最简单方法是什么?
最简单和最简单的解决方案是上述解决方案,因为:
Date列,您无需修改代码.编辑2:
Zohar Peled建议采用以下方式:
我会按照这个规则对行进行排序:首先,当null为空时,第二个,当date1为null时,第三个,当date2为null时,第四个,min(date1,date2)
因此,对于这种情况,可以通过使用相同的方法来达到解决方案,如下所示:
SELECT ID, Date1, Date2
FROM YourTable
ORDER BY
CASE WHEN Date1 IS NULL AND Date2 IS NULL THEN 0
WHEN Date1 IS NULL THEN 1
WHEN Date2 IS NULL THEN 2
ELSE 3 END,
(SELECT MIN(v) FROM (VALUES ([Date1]), ([Date2])) AS value(v))
Run Code Online (Sandbox Code Playgroud)
此代码的输出如下:

该COALESCE 解决方案 将不排序表这种方式.它弄乱了至少有一个NULL值的单元格的行.它的输出如下:

希望这有助于等待批评者.
如果你不希望使用Case statement的Order By,那么这是另一种方法,只需移动Case statement到Select
SELECT Id, Date1, Date2 FROM
(SELECT Id, Date1, Date2
,CASE WHEN Date1 < Date2 THEN Date1 ELSE Date2 END as MinDate
FROM YourTable) as T
ORDER BY MinDate
Run Code Online (Sandbox Code Playgroud)
这可能是一种不需要分支的替代解决方案CASE WHEN.这基于此处max(a,b)=1/2(a+b+|a?b|)描述的公式.我们使用参考日期()获得a和b的绝对值.DATEDIFF'1773-01-01'
ORDER BY (DATEDIFF(d,'17730101' ,isnull(Startdate,enddate)) + DATEDIFF(d,'17730101' ,isnull(EndDate,Startdate))
- ABS(DATEDIFF(d,isnull(Startdate,enddate),isnull(EndDate,Startdate))))
Run Code Online (Sandbox Code Playgroud)
测试数据
Create Table #DateData(ID int Identity, Name varchar(15),Startdate datetime,EndDate DateTime)
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-19 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-20 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-11 18:48:27','2015-04-22 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-05-09 18:48:27','2015-04-18 18:48:27')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 19:07:38','2015-04-17 18:55:38')
Insert Into #DateData(Name,Startdate,EndDate) values ('myName','2015-04-17 19:07:38','2015-05-12 18:56:29')
Run Code Online (Sandbox Code Playgroud)
完成查询
select *
from #DateData order by (DATEDIFF(d,'17730101' ,isnull(Startdate,enddate)) + DATEDIFF(d,'17730101' ,isnull(EndDate,Startdate))
- ABS(DATEDIFF(d,isnull(Startdate,enddate),isnull(EndDate,Startdate))))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4607 次 |
| 最近记录: |