首页 > 解决方案 > 在 SQL Server 的 WHERE 子句中使用 DATETIME

问题描述

我有这个查询

SELECT  
    [MsgNumber], [StateAfter],
    DATETIMEFROMPARTS (SUBSTRING([TimeString], 7, 4), 
                       SUBSTRING([TimeString], 4, 2), 
                       SUBSTRING([TimeString], 1, 2),
                       SUBSTRING([TimeString], 12, 2), 
                       SUBSTRING([TimeString], 15, 2), 
                       SUBSTRING([TimeString], 18, 2), 0) AS dt
FROM 
    TABLE
WHERE 
    [MsgNumber] IN (5, 9, 13, 17)
ORDER BY 
    dt ASC, StateAfter ASC

输出(好的):

+-----------+-----------+-------------------------+
| MsgNumber | tateAfter |           dt            |
+-----------+-----------+-------------------------+
|         9 |         1 | 2018-03-09 17:22:00.000 |
|         9 |         0 | 2018-03-09 17:23:37.000 |
|        17 |         1 | 2018-03-09 17:23:37.000 |
|        17 |         1 | 2018-03-09 17:29:43.000 |
|        17 |         1 | 2018-03-09 17:36:21.000 |
+-----------+-----------+-------------------------+

我想在日期上添加条件;为了避免内部日期时间编码错误,我使用 DATETIMEFROMPARTS 函数

SELECT [MsgNumber],[StateAfter]
,DATETIMEFROMPARTS ( SUBSTRING ( [TimeString] ,7 , 4 ), SUBSTRING ( [TimeString] ,4 , 2 ), SUBSTRING ( [TimeString] ,1 , 2 ),
                    SUBSTRING ( [TimeString] ,12 , 2 ), SUBSTRING ( [TimeString] ,15 , 2 ), SUBSTRING ( [TimeString] ,18 , 2 ) , 0) as dt
FROM TABLE
WHERE [MsgNumber] IN (5,9,13,17) AND (dt > DATETIMEFROMPARTS(2018,4,9,0,0,0,0) and dt <  DATETIMEFROMPARTS(2018,5,9,0,0,0,0))
ORDER BY dt ASC,StateAfter ASC

错误:-

Messaggio 207、livello 16、stato 1、riga 5
列名“dt”无效。
Messaggio 207、livello 16、stato 1、riga 5
列名“dt”无效。

有人可以帮我理解为什么它不起作用吗?我也尝试了 BETWEEN 子句;谢谢

标签: sqlsql-servertsqldatetimewhere-clause

解决方案


您不能在where子句中引用列别名。典型的解决方案是使用子查询或 CTE。但是 SQL Server 有另一种我喜欢的方法apply

SELECT [MsgNumber], [StateAfter], v.dt
FROM TABLE t CROSS APPLY
     (VALUES (DATETIMEFROMPARTS(SUBSTRING ([TimeString], 7, 4), SUBSTRING([TimeString], 4, 2), SUBSTRING([TimeString], 1, 2),
                    SUBSTRING([TimeString], 12, 2), SUBSTRING( [TimeString], 15, 2), SUBSTRING([TimeString], 18, 2), 0)
             )
     ) V(dt)
WHERE [MsgNumber] IN (5, 9, 13, 17) AND
      v.dt > DATETIMEFROMPARTS(2018, 4, 9, 0, 0, 0, 0) AND
      v.dt <  DATETIMEFROMPARTS(2018, 5, 9, 0, 0, 0, 0))
ORDER BY dt ASC,StateAfter ASC;

我觉得奇怪的是你不使用更简单的:

WHERE [MsgNumber] IN (5, 9, 13, 17) AND
      v.dt > '20180409'  AND
      v.dt < '20180509'

(我没有使用连字符,因为无论国际化设置如何,这种格式总是被解释为 YYYYMMDD。)


推荐阅读