获取当前月份和日期的最佳方式,但使用静态年份

时间:2016-08-24 23:16:35

标签: mysql sql

我有一个表格,用于存储“开始”和“结束”日期以及其他各种行,例如:

s_d = 2000-01-01

e_d = 2000-05-17

我想从表格中提取一些行,具体取决于当前日期是否落在开始和结束日期之间,但我似乎无法使其正常工作。

我使用的是静态年份(2000年),因为我真的不知道如何仅使用月份和日期来比较日期。

$q = "SELECT 
    xxx, 
    yyy,    
    c_d,
    e_d,
    DATE('2000-'.DATE('m').'-'.DATE('d')) AS c_d
    FROM mytable
    WHERE c_d >= s_d AND c_d <= e_d";

上面的代码不起作用,我已经尝试过转换,例如:CAST('datestuff'AS DATE),或使用php变量而没有运气。我吮吸与日期相关的东西。

我的s_d和e_d行是“DATE NOT NULL”字段,所以我确定它与我创建的c_d(当前日期)有关。

更新(仍在测试):

这似乎运作良好,某些部分可能是多余的(在s_d&amp; e_d上使用date_format),但它可以防止我以后搞乱。

在MONTH / DAY(NOW())上使用DATE_FORMAT将创建一个前导0以匹配表中存储的s_d和e_d。

$q = "SELECT xxx
    , s_d
    , e_d
    FROM mytable
    WHERE DATE_FORMAT(CONCAT('2000', '-', MONTH(NOW()), '-', DAY(NOW())), '%Y-%m-%d') >= DATE_FORMAT(s_d, '%Y-%m-%d') 
    AND DATE_FORMAT(CONCAT('2000', '-', MONTH(NOW()), '-', DAY(NOW())), '%Y-%m-%d') <= DATE_FORMAT(e_d, '%Y-%m-%d')
    AND xxx = '$xxx'";

2 个答案:

答案 0 :(得分:0)

在一般情况下,您要比较可能跨越年界的两个日期...您的代码应该有效。或者你可以使用

将@d声明为datetime = GETDATE(); // SQL Server

$q = "SELECT 
    xxx, 
    yyy,    
    c_d,
    e_d,
    DATE('2000-'.DATE('m').'-'.DATE('d')) AS c_d
    FROM mytable
    WHERE @d BETWEEN c_d >= s_d AND c_d <= e_d";
select Date, TotalAllowance from Calculation where EmployeeId = 1
                 and Date between s_d and e_d

使用

declare @d as datetime = NOW(); 

用于其他版本的SQL

如果您想忽略年份,请使用MONTH(@d)和DAY(@d)

答案 1 :(得分:0)

您遇到的一个问题是SQL字符串无效。

如果您打算使用PHP DATE函数返回两位数的月份和两位数日,作为SQL文本中的文字,那么那些需要作为PHP字符串的一部分进行评估,而不是作为一部分传递给MySQL SQL文本。

也就是说,您的PHP代码看起来像这样:

 $sql="SELECT ... 
            , DATE('2000-" . DATE('m') . "-" . DATE('d') . "') AS c_d
            , ...
         FROM ... 
        WHERE ... ";

当PHP计算表达式为$ sql变量赋值时,该字符串将包含如下内容:

       SELECT ... 
            , DATE('2000-08-24') AS c_d
            , ...
         FROM ... 
        WHERE ... "

这对于有效的MySQL语法有更好的准备。

此外,引用(在WHERE子句中)SELECT列表中分配给该表达式的别名无效。

只比较日期值的月份和日期部分,这有点棘手。

您的条件不会匹配start_date所在的行2015-12-25&#39;结束日期为2016-01-15&#39;。

就MySQL而言,您可以使用DATE_FORMAT函数返回月和日,

 SELECT t.s_d
      , DATE_FORMAT(t.s_d,'%m%d') AS s_mmdd
      , t.e_d
      , DATE_FORMAT(t.e_d,'%m%d') AS e_mmdd

这些表达式可以在WHERE子句中使用

 WHERE DATE_FORMAT(t.s_d,'%m%d') <= '0824'
   AND DATE_FORMAT(t.e_d,'%m%d') >= '0824'

请注意,这将迫使MySQL为表中的每一行评估这些表达式。为了获得范围扫描的可能性,您正处于正常化的轨道上,正常化&#34; s_d和e_d作为静态年份,并将其存储为列。或者只是将月份和日期作为字符串存储在规范化的&#34; s_mmdd&#34;和&#34; e_mmdd&#34;列。

再次......这只有在start_date的mmdd低于end_date的mmdd时才有效。 (我之前提到的问题,日期范围跨越一年边界。)

要获得这些行的匹配,您需要识别它们,然后&#34;翻转&#34;大于/小于范围检查中的条件。 (或者在检查这些行时交换s_mmdd和e_mmdd。)