【问题标题】:SQL Server datetime LIKE select?SQL Server 日期时间 LIKE 选择?
【发布时间】:2010-12-10 09:16:03
【问题描述】:

在 MySQL 中

select * from record where register_date like '2009-10-10%'

SQL Server 中的语法是什么?

【问题讨论】:

  • 您真正想要检查什么?给定的日期时间有给定的日期部分?还是别的什么?
  • 有关此问题的健康讨论(包括为什么将 DATETIME 值视为字符串不好,以及为什么使用 BETWEEN>= AND <= 可能不好),请参阅 this blog by Aaron Bertrand
  • 您的问题至少有5like-operator 标签的投票。能否请您将sql-like 推荐为synonym

标签: sql-server sql-like


【解决方案1】:

我意识到这是一个老问题,但这里的很多答案都没有给出 SARGable 答案,也没有涵盖参数化。

首先,您最好使用>=< 逻辑。对于您想要的日期,那将如下所示:

SELECT {Your Columns}
FROM dbo.record
WHERE register_date >= '20091010'
  AND register_date < '20091011';

这将包括 2009 年 10 月 10 日的每个时间值,包括当天的午夜钟声,以及 2009 年 10 月 11 日之前的纳秒。

但是,您通常会对查询进行参数化,因此您可以改为使用 DATEADD 在第二个子句中添加一天:

DECLARE @DateParam date = '20091010';

SELECT {Your Columns}
FROM dbo.record
WHERE register_date >= @DateParam
  AND register_date < DATEADD(DAY,1,@DateParam);

这保持了 SARGability 并意味着可以使用 register_date 上的任何索引。

【讨论】:

    【解决方案2】:

    试试这个

    SELECT top 10 * from record WHERE  IsActive = 1 and CONVERT(VARCHAR, register_date, 120) LIKE '2020-01%'
    

    【讨论】:

      【解决方案3】:

      我对这个线程有点晚了,但实际上 MS SQL 服务器中直接支持 like 运算符。

      如 LIKE 帮助中所述,如果数据类型不是字符串,则会尝试将其转换为字符串。正如 cast\convert 文档中所述:

      默认日期时间转换为字符串类型为 0 (,100),即 mon dd yyyy hh:miAM(或 PM)。

      如果你在数据库中有这样的日期:

      2015-06-01 11:52:59.057
      

      然后你做这样的查询:

      select * from wws_invoice where invdate like 'Jun%'
      select * from wws_invoice where invdate like 'Jun 1%'
      select * from wws_invoice where invdate like 'Jun 1 %'
      select * from wws_invoice where invdate like 'Jun 1 2015:%'
      select * from wws_invoice where invdate like 'Jun ? 2015%'
      ...
      select * from wws_invoice where invdate like 'Jun 1 2015 11:52AM'
      

      你得到那一行。

      但是,这种日期格式表明它是 DateTime2,然后文档说:

      21 或 121 -- ODBC 规范(以毫秒为单位)默认时间, 日期、日期时间 2 和日期时间偏移量。 -- yyyy-mm-dd hh:mi:ss.mmm(24h)

      这样更容易,您可以使用:

      select * from wws_invoice where invdate like '2015-06-01%'
      

      并获取发票记录。这是一个演示代码:

      DECLARE @myDates TABLE (myDate DATETIME2);
      INSERT INTO @myDates (myDate)
      VALUES
      ('2015-06-01 11:52:59.057'),
      ('2015-06-01 11:52:59.054'),
      ('2015-06-01 13:52:59.057'),
      ('2015-06-01 14:52:59.057');
      
      SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01%';
      SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01 11%';
      SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01 11:52:59%';
      SELECT * FROM @myDates WHERE myDate LIKE '2015-06-01 11:52:59.054%';
      

      在没有任何转换为​​字符串的情况下在 SQL Server 中进行日期时间搜索一直存在问题。获取每个日期部分是一种矫枉过正(不太可能使用索引)。当您不使用字符串转换时,可能更好的方法是使用范围检查。即:

      select * from record 
      where register_date >= '20091010' and register_date < '20091011';
      

      【讨论】:

        【解决方案4】:

        我就是这样解决了我的问题。感谢您提出改进建议。 C# 中的示例。

        string dd, mm, aa, trc, data;
        dd = nData.Text.Substring(0, 2);
        mm = nData.Text.Substring(3, 2);
        aa = nData.Text.Substring(6, 4);
        trc = "-";
        data = aa + trc + mm + trc + dd;
        
        "Select * From bdPedidos Where Data Like '%" + data + "%'";
        

        【讨论】:

          【解决方案5】:

          LIKE 运算符不适用于月份或日期等日期部分,但 DATEPART 运算符可以。

          查找所有开户日期为 1 日的账户的命令:

          SELECT * 
            FROM Account 
           WHERE DATEPART(DAY, CAST(OpenDt AS DATE)) = 1`
          

          *CASTING OpenDt 因为它的值在DATETIME 而不仅仅是DATE

          【讨论】:

            【解决方案6】:

            很遗憾,无法使用“LIKE”将日期时间与 varchar 进行比较 但是可以通过另一种方式获得所需的输出。

                select * from record where datediff(dd,[record].[register_date],'2009-10-10')=0
            

            【讨论】:

              【解决方案7】:

              您可以使用 DATEPART() 函数

              SELECT * FROM record 
              WHERE  (DATEPART(yy, register_date) = 2009
              AND    DATEPART(mm, register_date) = 10
              AND    DATEPART(dd, register_date) = 10)
              

              我发现这种方式易于阅读,因为它忽略了时间部分,而且您不必使用第二天的日期来限制您的选择。您可以通过添加额外的子句,使用适当的 DatePart 代码来达到更大或更小的粒度,例如

              AND    DATEPART(hh, register_date) = 12)
              

              获取 12 到 1 之间的记录。

              请参阅MSDN DATEPART docs 以获取有效参数的完整列表。

              【讨论】:

              • 如果 register_date 上有索引,这将完全忽略索引并且性能会受到影响。可能非常糟糕。
              • 好的,但它确实避免了使用与相关日期后一天等效的字符串的问题,这里的一些答案中建议了这一点。棘手的日期是月末或年末。
              【解决方案8】:

              对于 SQL Server 中的日期,LIKE 运算符的覆盖率非常不稳定。它仅适用于美国日期格式。例如,您可以尝试:

              ... WHERE register_date LIKE 'oct 10 2009%'
              

              我已经在 SQL Server 2005 中对此进行了测试,它确实有效,但您确实需要尝试不同的组合。我注意到的奇怪的事情是:

              • 对于日期内的不同子字段,您似乎只能获得全部或全部信息,例如,如果您搜索“apr 2%”,您只会在 20 日获得任何信息 - 它会忽略 2 日。

              • 使用单个下划线“_”来表示单个(通配符)字符并不完全有效,例如,WHERE mydate LIKE 'oct _ 2010%'全部返回日期在 10 日之前 - 实际上它什么都不返回!

              • 格式是严格的美式:'mmm dd yyyy hh:mm'

              我发现很难确定一个 LIKEing 秒的过程,所以如果有人想更进一步,请成为我的客人!

              希望这会有所帮助。

              【讨论】:

                【解决方案9】:

                您还可以使用 convert 使日期可使用 LIKE 进行搜索。例如,

                select convert(VARCHAR(40),create_date,121) , * from sys.objects where     convert(VARCHAR(40),create_date,121) LIKE '%17:34%'
                

                【讨论】:

                  【解决方案10】:

                  没有直接支持 LIKE 运算符针对 DATETIME 变量,但您始终可以将 DATETIME 强制转换为 VARCHAR:

                  SELECT (list of fields) FROM YourTable
                  WHERE CONVERT(VARCHAR(25), register_date, 126) LIKE '2009-10-10%'
                  

                  查看MSDN docs 以获取 CONVERT 函数中可用“样式”的完整列表。

                  马克

                  【讨论】:

                  • 同意 - 但 OP 要求一种使用 LIKE 处理日期时间的方法...。但我同意 - 最好使用 >= 和
                  • 谢谢大家。对不起,我只是 SQL 的新手。
                  • 请注意,MSSQL 2012(我猜也是旧版本)会将 datetime 转换为 varchar 为 '2014-01-06T16:18:00.045',因此如果您尝试匹配,请记住这一点小时/分钟。
                  • 我对上述 sql 选择的唯一问题是:WHERE CONVERT(VARCHAR(25), register_date, 25) LIKE '2009-10-10%'
                  【解决方案11】:

                  您可以使用 CONVERT 以文本形式获取日期。如果将其转换为 varchar(10),则可以使用 = 而不是 like:

                  select *
                  from record
                  where CONVERT(VARCHAR(10),register_date,120) = '2009-10-10'
                  

                  或者您可以使用上限和下限日期,另外还有一个好处是可以使用索引:

                  select *
                  from record
                  where '2009-10-10' <= register_date
                  and register_date < '2009-10-11'
                  

                  【讨论】:

                  • 我觉得where子句有错字,应该是"where '2009-10-10' >= register_date"
                  • @mr_eclair:不这样认为,这将包括 10 月 11 日之前的每个日期
                  【解决方案12】:

                  如果你这样做,你就是在强制它进行字符串转换。最好建立一个开始/结束日期范围,并使用:

                  declare @start datetime, @end datetime
                  select @start = '2009-10-10', @end = '2009-11-10'
                  select * from record where register_date >= @start
                             and register_date < @end
                  

                  这将允许它使用索引(如果register_date 上有一个),而不是表扫描。

                  【讨论】:

                  • 谢谢。对不起,我只是 SQL 的新手。
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-08-09
                  • 1970-01-01
                  • 2016-07-18
                  • 1970-01-01
                  • 2013-09-08
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多