考虑下表daterange
_date trading_day
------------------------
2011-08-01 1
2011-07-31 0
2011-07-30 0
2011-07-29 1
2011-07-28 1
2011-07-27 1
2011-07-26 1
2011-07-25 1
2011-07-24 0
2011-07-23 0
2011-07-22 1
2011-07-21 1
2011-07-20 1
2011-07-19 1
2011-07-18 1
2011-07-17 0
我需要一个在给定的_date之前返回_date
,x
天的查询。倒计时时,_days
与trading_day = 0
应该被忽略。几个例子:
input | output
-------------------------+------------
1 day before 2011-07-19 | 2011-07-18
2 days before 2011-08-01 | 2011-07-28 (trading_day = 0 don't count)
3 days before 2011-07-29 | 2001-07-26
第一个很简单:
SELECT _date
FROM daterange
WHERE trading_day = 0 AND _date < '2011-07-19' LIMIT 1
但我不知道如何查询其他示例。你呢?我倾向于一个适用于所有情况的解决方案,所以我可以在PHP中向后变换一个变量。
答案 0 :(得分:3)
查询1
SELECT `_date`
FROM `daterange`
WHERE `trading_day` = '1' AND `_date` <= '2011-07-19'
ORDER BY `_date` DESC
LIMIT 1
OFFSET 1;
查询2
SELECT `_date`
FROM `daterange`
WHERE `trading_day` = '1' AND `_date` <= '2011-08-01'
ORDER BY `_date` DESC
LIMIT 1
OFFSET 2;
查询3
SELECT `_date`
FROM `daterange`
WHERE `trading_day` = '1' AND `_date` <= '2011-07-29'
ORDER BY `_date` DESC
LIMIT 1
OFFSET 3;
准备好的声明(PDO示例)
$stmt = $dbh->prepare("SELECT `_date`
FROM `daterange`
WHERE `trading_day` = '1' AND `_date` <= :given_date
ORDER BY `_date` DESC
LIMIT 1
OFFSET :days_before");
$stmt->bindParam(':given_date', $given_date);
$stmt->bindParam(':days_before', $days_before);
$stmt->execute();
答案 1 :(得分:1)
SELECT DATE(_date - INTERVAL trading_day DAY) FROM daterange;
当交易日为0并且只返回日期时,此查询将忽略。如果您想排除没有交易日的日期,那么您需要:
SELECT DATE(_date - INTERVAL trading_day DAY) FROM daterange WHERE trading_day!=0;
如果您的日期字段已经是格式2012-01-01,则此处也不需要DATE()。如果您的日期字段是时间戳(2012-01-01 10:01:17),则DATE()将仅返回日期部分(2012-01-01)。客栈换句话说,根据你所呈现的内容,这对你也同样适用:
SELECT _date - INTERVAL trading_day DAY FROM daterange;
因此
SELECT _date - INTERVAL trading_day DAY FROM daterange WHERE trading_day!=0;
答案 2 :(得分:1)
您的第一个示例现在只是意外运行:)您需要对结果集应用订单,以确保检索2011-07-19之前的最大日期,而不仅仅是任意日期。
SELECT _date
FROM daterange
WHERE trading_day <> 0 AND _date < '2011-07-19'
ORDER BY _date DESC
LIMIT 1
如果您想要的不是某一天之前的第一天,而是某一天,那么也会在您的查询中应用OFFSET。
这个将为您提供#3所需的内容:
SELECT _date
FROM daterange
WHERE trading_day <> 0 AND _date < '2011-07-29'
ORDER BY _date DESC
LIMIT 1
OFFSET 2
OFFSET 2
指示MySQL跳过本应返回的前两个结果,并从第三个结果开始。
答案 3 :(得分:1)
我对你的问题并不完全清楚 - 但似乎你想要选择之前的交易日期,以及多少天以前。我不确定你是否想对表格中的所有日期或任何单一日期这样做。
我假设它适用于表格中的所有日期,因为否则这是一个非常简单的查询。
SELECT
dr._date as the_date,
d2._date as previous_trading_date,
DATEDIFF(dr._date, d2._date) days_ago
FROM daterange dr
JOIN (
SELECT _date FROM daterange
WHERE trading_day > 0
ORDER BY _date DESC
) d2 ON d2._date < dr._date
GROUP BY dr._date
ORDER BY dr._date DESC
此查询的作用是从日期范围中选择每个日期,然后运行子查询以选择每个日期减去非交易日的日期,并按降序排序(最近的第一个)。它将每个日期连接到它之前的每个日期,但我们然后按daterange._date
分组才能获得第一行(这将是交易日的第一个日期,因为我们做了子日期 - 与订单条款一起选择)。然后,我们使用DATEDIFF()
函数计算日期和上一个交易日期之间的天数。
因此,如果您要选择之前的日期,该日期是指定日期($x
)之前的某些数字($date
),并忽略具有trading_day
值的日期0
,你会这样做:
SELECT _date
FROM daterange
WHERE _date < '{$date}'
AND trading_day > 0
ORDER BY _date DESC
LIMIT 1
OFFSET {$x - 1}
OFFSET
子句允许您跳过与{$x - 1}
条款匹配的前WHERE
天,这些条款应该会到达您想要的日期。这个查询做了一些假设。主要是每天daterange
上有一行(且只有一行)。如果你不这样做,那么你最终会得到一些意想不到的结果。
但在考虑之后,你可以做类似这样的查询:
SELECT _date
FROM daterange
WHERE _date <= DATE_SUB('2011-08-01', INTERVAL {$x} DAY)
AND trading_day > 0
ORDER BY _date DESC
LIMIT 1
此查询执行日期减法,因此您将返回{$x}
天之前的日期,但通过添加trading_day > 0
子句,它将删除任何非交易日的日期,按降序日期顺序排列结果,然后选择第一个 - 应该是您想要的日期。尝试一下。
答案 4 :(得分:0)
Select temp._date
FROM (Select _date FROM daterange WHERE trading_day<>0 AND trading_day < $date ORDER BY _date) as temp
ORDER BY _date LIMIT $days_before;
只获得第一张唱片。
您也可以将ORDER BY更改为DESC,并将封闭的select中的where子句更改为将来。