You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL查询问题:合并门店营业状态查询,解决跨天判断错误

解决跨天营业门店的单条查询状态判断问题

嘿,我来帮你搞定这个跨天营业门店的状态判断和重复输出问题!你的核心痛点是单条查询区分营业/停业,且每个门店只显示一次,之前的查询因为基于business_hour的每条记录判断,导致重复输出,而且停业的逻辑也不对——只要门店有任意一条营业时间满足当前营业,它就应该是OPEN状态,只有所有时间段都不满足才是CLOSED。

问题根源分析

  • 你之前的查询从business_hour表出发,每个门店有多条营业时间记录,所以会重复输出同一门店的状态;
  • 停业判断逻辑错误:你之前的查询会把不满足当前营业的单条记录标记为CLOSED,但实际上只要有一条记录满足营业,门店就是OPEN的。

解决方案:单条SQL实现门店状态唯一输出

我们可以从restaurant表出发,用EXISTS子查询判断每个门店是否存在有效的营业记录,再用CASE WHEN标记状态,同时通过GROUP BY确保每个门店只显示一次。另外,一定要用参数绑定避免SQL注入,别直接把变量拼进SQL里!

最终SQL查询(带PHP PDO实现)

// 获取当前星期几(和表中openday/closeday格式一致,比如'Monday')
$today = date('l');
// 获取当前时间(比如'07:00:00')
$timeNow = date('H:i:s');

// 准备SQL语句,用参数绑定
$stmt = $pdo->prepare("
    SELECT 
        r.id AS restaurantID,
        r.name, -- 替换成你restaurant表中的实际字段
        CASE 
            WHEN EXISTS (
                SELECT 1 FROM business_hour bh
                WHERE bh.restaurantID = r.id
                AND (
                    -- 情况1:非跨天营业,当前时间在当天开门/关门区间内
                    (bh.openday = :today AND bh.closeday = :today AND bh.opentime <= :timeNow AND bh.closetime >= :timeNow)
                    -- 情况2:跨天营业,今天是结束日,当前时间还没到关门时间
                    OR (bh.closeday = :today AND bh.closetime >= :timeNow)
                    -- 情况3:跨天营业,今天是开始日,当前时间已经过了开门时间
                    OR (bh.openday = :today AND bh.opentime <= :timeNow)
                )
            ) THEN 'OPEN'
            ELSE 'CLOSED'
        END AS status
    FROM restaurant r
    GROUP BY r.id, r.name
");

// 绑定参数
$stmt->bindParam(':today', $today);
$stmt->bindParam(':timeNow', $timeNow);
$stmt->execute();

// 输出结果
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
    echo "{$row['restaurantID']} {$row['status']} - {$row['name']}<br>";
}

逻辑说明

  • EXISTS子查询:检查当前门店是否存在任意一条满足营业条件的时间段,只要有一条符合,就标记为OPEN;
  • GROUP BY r.id, r.name:确保每个门店只返回一条记录,避免重复;
  • 参数绑定:用:today和:timeNow代替直接拼接变量,彻底避免SQL注入风险。

可选扩展:显示当前营业时间段

如果你想给OPEN的门店显示当前的营业区间,可以调整SQL,添加子查询获取对应的时间段:

SELECT 
    r.id AS restaurantID,
    r.name,
    CASE 
        WHEN EXISTS (
            SELECT 1 FROM business_hour bh
            WHERE bh.restaurantID = r.id
            AND (
                (bh.openday = :today AND bh.closeday = :today AND bh.opentime <= :timeNow AND bh.closetime >= :timeNow)
                OR (bh.closeday = :today AND bh.closetime >= :timeNow)
                OR (bh.openday = :today AND bh.opentime <= :timeNow)
            )
        ) THEN 'OPEN'
        ELSE 'CLOSED'
    END AS status,
    -- 获取当前有效的营业时间段(仅OPEN门店有值)
    (SELECT CONCAT(bh.openday, ' ', bh.opentime, ' -- ', bh.closeday, ' ', bh.closetime) 
     FROM business_hour bh
     WHERE bh.restaurantID = r.id
     AND (
         (bh.openday = :today AND bh.closeday = :today AND bh.opentime <= :timeNow AND bh.closetime >= :timeNow)
         OR (bh.closeday = :today AND bh.closetime >= :timeNow)
         OR (bh.openday = :today AND bh.opentime <= :timeNow)
     ) LIMIT 1) AS current_business_hours
FROM restaurant r
GROUP BY r.id, r.name;

这样输出时,OPEN的门店会显示当前的营业时段,CLOSED的门店该字段为NULL,你可以根据需求处理显示逻辑。

内容的提问来源于stack exchange,提问作者Rohis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:34:54