我正在编写一个MySQL查询作为Laravel项目的一部分,这将允许我只返回符合特定条件的记录。
对于此解决方案,我有以下数据库迁移:
Schema::create('slides', function (Blueprint $table) {
$table->increments('id');
$table->integer('order')->default(0);
$table->boolean('enabled')->default(0);
$table->dateTime('start')->nullable();
$table->dateTime('end')->nullable();
});
理论上这将被查询如下(这不是正确的SQL!):
SELECT * FROM slides
IF enabled == 1
IF start IS NOT NULL
Only return the record if the current timestamp is after start
IF end IS NOT NULL
Only return the record if the current timestamp is before end
ORDER BY order ASC
重要的是要记住,开始和结束都不依赖于另一个 - 我可以设置开始日期和结束日期,并使其从开始日期无限期出现。这同样适用于结束日期。
我有一些工作代码,改编自当前的答案,似乎工作正常,但看起来很复杂:
SELECT *
FROM slides
WHERE `enabled` = 1
AND ((`start` < NOW() AND `end` > NOW()) OR (`start` IS NULL AND `end` > NOW()) OR (`start` < NOW() AND `end` IS NULL) OR (`start` IS NULL AND `end` IS NULL))
ORDER BY `order`
后续 在Spencer的解决方案(已接受的解决方案)的帮助下,我成功创建了Eloquent代码,使我能够执行此查询。作为参考,这里是:
$slides = Slide::where('enabled', true)
->where(function($query) {
return $query->where('start', '<', Carbon::now()->toDateTimeString())
->orWhereNull('start');
})
->where(function($query) {
return $query->where('end', '>', Carbon::now()->toDateTimeString())
->orWhereNull('end');
})
->orderBy('order', 'asc')
->get();
答案 0 :(得分:2)
@strawberry在他的评论中已经提到过,但没有人接受它:
select * from slides where
coalesce(start,'1900-1-1')<now()
and coalesce(end,'3000-12-31')>now()
选择的日期如'1900-1-1'
等应该被选为&#34;之前&#34; &#34;&#34;&#34;&#34;任何可预期的日期。
这样,如果日期实际上是一个值,则只会对日期进行有意义的比较。
答案 1 :(得分:1)
我认为逻辑是这样的:
select s.*
from slides s
where ((enabled = 1 and start is not null and current_timestamp > start) and
(enabled = 1 and end is not null and current_timestamp < end)
) or
(enabled <> 1 or enabled is null)
order by order asc;
答案 2 :(得分:1)
我认为像这样的查询会满足要求。 (我假设->dateTime
表示MySQL列被定义为数据类型DATETIME
或TIMESTAMP
。)
SELECT s.id
, s.order
, s.enabled
, s.start
, s.end
FROM slides s
WHERE s.enabled = 1
AND ( s.start <= NOW() OR s.end >= NOW() )
ORDER BY s.order
我们将规范“当前时间戳在启动后”表示“起始列小于或等于当前时间戳”。我们将规范称为“结束大于或等于当前时间戳”。 (一个问题是相等条件的极端情况,当开始或结束与当前时间戳完全匹配时。)
<强>后续强>
上述查询不处理start
或end
为NULL的情况。
我想我现在更好地理解规范(基于评论和问题的更新。)
OP希望返回当前日期时间(现在)在开始和结束之间的行...基本上是当前活动的“幻灯片”。
但OP希望start
中的NULL值与“之前”相同,而end
中的NULL值与“after now”相同。
可以这样表达:
SELECT s.id
, s.order
, s.enabled
, s.start
, s.end
FROM slides s
WHERE s.enabled = 1
AND ( s.start < NOW() OR s.start IS NULL )
AND ( s.end > NOW() OR s.end IS NULL )
ORDER BY s.order