SQL选择特定日期的查询

时间:2013-08-17 11:30:21

标签: sql sql-server-2005 sql-server-2012

我的表格如下所示

tbPatientEpisode
EpisodeIDP    int
EpisodeNumber varcher
EpisodeDate   datetime

尝试使用以下SQL查询时

SELECT * FROM tbPatientEpisode
它显示了如下图像的结果..

Result

我想要特定日期的数据,如2013-01-22,我试过以下SQL查询

SELECT * FROM tbPatientEpisode where EpisodeDate  like '%2013-01-22%'

但它不会返回任何行。我的查询有什么问题,或者是否有任何正确的方法来获得这种结果......任何帮助都会受到欢迎。

4 个答案:

答案 0 :(得分:2)

不要在日期列上使用,它不会起作用。

相反(SQL Server 2008以后):

SELECT * 
FROM tbPatientEpisode 
where CAST(EpisodeDate as Date) = '2013-01-22'

注意:此表单不会使用以列EpisodeDate

开头的任何适用索引

如果要确保使用任何适用的索引(并且适用于SQL Server 2005):

SELECT * 
FROM tbPatientEpisode 
where EpisodeDate between = '2013-01-22 00:00:00' AND '2013-01-22 23:59:59.997'

答案 1 :(得分:2)

那是因为您的列EpisodeDate是日期时间类型。 您可以将EpisodeDate强制转换为日期时间,但它会阻止在列上使用索引,因此我知道最好的方法是将EpisodeDate与两个日期时间进行比较:

SELECT *
FROM tbPatientEpisode
where
    EpisodeDate >= convert(datetime, '20130122', 112) and 
    EpisodeDate < dateadd(day, 1, convert(datetime, '20130122', 112))

我会解释一下:

首先,您可以将EpisodeDate与字符串进行比较而不进行转换,并依赖于隐式SQL Server转换,但您应该注意两件事:

  • Priority of types。比较不同类型的valus时,优先级较低的数据将转换为优先级较高的类型。在我们的情况下这很好,因为varchardatetime具有更低的优先级,但是例如,当您的列为varchar并且您想要将其与{{{{}}进行比较时,它可能会阻止使用索引1}}。
  • 您必须知道SQL服务器如何将您的字符串转换为日期。例如,SQL服务器可以轻松识别格式YYYYMMDD,但总的来说,我认为明确转换数据是一种很好的做法。

所以你可以使用

datetime

但你必须确定你知道自己在做什么

我没有指定select * FROM tbPatientEpisode where EpisodeDate >= '20130122' and EpisodeDate < '20130123' 而不指定dateadd(day, 1, '20130122'),因为我正在考虑将20130122作为输入参数,因此您可以在我的查询中替换此字符串

答案 2 :(得分:1)

基于执行计划,通过使用LIKE,系统会将所有列类型转换为VARCHAR,然后只执行扫描

为什么查询中没有结果返回?这是因为系统已经日期时间转换为 nvarchar ,这类似于 2013年1月22日上午10:55

这就是为什么没有结果返回

尝试将您的查询更改为

SELECT * FROM tbPatientEpisode where EpisodeDate  like '%Jan 22 2013%'

这应该可以正常工作,以下是使用LIKE的另一种方式,将你的episodeDate投射到某种格式,如'2013-01-22'

 SELECT * FROM tbPatientEpisode where CONVERT(NVARCHAR(25),EpisodeDate,126) 
 like '%2013-01-22%'

最后我希望我的解释能够帮助你理解究竟发生了什么,欢呼兄弟=)

答案 3 :(得分:0)

这个答案首先尝试解释为什么EpisodeDate like '%2013-01-22%'解决方案不起作用,你可以做些什么来使用like ...获得所需的结果(我不推荐),最后,我提出了两个解决方案(有和没有隐式转换)。所有查询都可以在AdventureWorks2008R2 sample database上执行:

/*
CREATE INDEX IX_SalesOrderHeader_OrderDate
ON Sales.SalesOrderHeader(OrderDate)
*/

-- It CONVERTs datetime values to VARCHAR with style 0 {Style 0 = mon dd yyyy hh:miAM (or PM)}
-- http://technet.microsoft.com/en-us/library/ms187928.aspx
SELECT  TOP(1500)
        h.OrderDate,h.SalesOrderID, 
        CONVERT(VARCHAR(40),h.OrderDate,0) AS OrderDateAsVarChar40, -- Explicit conversion from DATETIME to VARCHAR(40) with style 0
        LEFT(h.OrderDate,40) AS ForcingImplicitConvertOnDateTimeColumn -- Implicit conversion because the first argument of LEFT function must be a %CHAR
FROM    Sales.SalesOrderHeader h;
/*
OrderDate               SalesOrderID OrderDateAsVarChar40 ForcingImplicitConvertOnDateTimeColumn
----------------------- ------------ -------------------- --------------------------------------
2005-07-01 00:00:00.000 43659        Jul  1 2005 12:00AM  Jul  1 2005 12:00AM
...
2005-11-19 00:00:00.000 44685        Nov 19 2005 12:00AM  Nov 19 2005 12:00AM
2005-11-20 00:00:00.000 44686        Nov 20 2005 12:00AM  Nov 20 2005 12:00AM
...
2008-07-31 00:00:00.000 75123        Jul 31 2008 12:00AM  Jul 31 2008 12:00AM
*/

-- Result: No rows
SELECT  h.OrderDate,h.SalesOrderID
FROM    Sales.SalesOrderHeader h
-- The syntax of LIKE operator shows that h.OrderDate must be %CHAR
-- so, SQL Server add an implicit conversion of OrderDate values from DATETIME to VARCHAR
-- http://technet.microsoft.com/en-us/library/ms179859.aspx
WHERE   h.OrderDate LIKE '%2005-11-20%'

执行计划: enter image description here

-- Result: 5 rows 
-- I get 5 rows but it's the execution plan is unoptimized (because of Index Scan; see first execution plan)
SELECT  h.OrderDate,h.SalesOrderID
FROM    Sales.SalesOrderHeader h
WHERE   h.OrderDate LIKE 'Nov 20 2005%';

-- Result: 5 rows 
-- I get 5 rows and the execution plan includes 
-- (1) Index Seek operator instead of Index Scan
-- (2) and implicit conversion of @1 and @2 parameters from varchar to datetime
SELECT  h.OrderDate,h.SalesOrderID
FROM    Sales.SalesOrderHeader h
WHERE   h.OrderDate >= '20051120' AND h.OrderDate < '20051121';

执行计划: enter image description here

-- Result: 5 rows 
-- I get 5 rows and the execution plan includes 
-- (1) Index Seek operator instead of Index Scan
-- (2) and no implicit conversion of @1 and @2 parameters
-- See Date, Time, and Timestamp Literals: http://msdn.microsoft.com/en-us/library/windows/desktop/ms710282(v=vs.85).aspx
SELECT  h.OrderDate,h.SalesOrderID
FROM    Sales.SalesOrderHeader h
WHERE   h.OrderDate >= {d '2005-11-20'} AND h.OrderDate < {d '2005-11-21'};

执行计划: enter image description here