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

Symfony2+Doctrine2中用DATE_ADD聚合查周起止日期报错求助

解决Doctrine QueryBuilder中日期周范围查询的语法错误问题

你遇到的错误核心原因是Doctrine的DQL不支持原生MySQL的INTERVAL(...) DAY语法——DQL有自己的日期函数规范,和原生SQL写法不同。下面给你两种可行的解决方案,优先推荐第一种用DQL内置函数的方式:

方案一:使用Doctrine内置的DATE_ADD函数(推荐)

Doctrine的DATE_ADD函数语法是:DATE_ADD(date, interval, unit),其中unit是字符串类型(比如'DAY'、'MONTH'),而不是原生MySQL的INTERVAL X DAY格式。同时注意修正你代码里的几个小问题:

  1. 移除week_number里多余的右括号
  2. 如果r.eventDate已经是DateTime类型,不需要用STR_TO_DATE转换,直接使用字段即可

修改后的完整QueryBuilder代码:

$qb = $this->createQueryBuilder('r');
$query = $qb->select([
        "COUNT(r.id) as events_amount",
        "MAX(r.eventDate) AS event_date",
        "DATE(DATE_ADD(r.eventDate, (1 - DAYOFWEEK(r.eventDate)), 'DAY')) AS start_of_week",
        "DATE(DATE_ADD(r.eventDate, (7 - DAYOFWEEK(r.eventDate)), 'DAY')) AS end_of_week",
        "WEEK(r.eventDate) AS week_number"
    ])
    ->where('r.eventDate BETWEEN :start_date AND :end_date')
    ->groupBy('week_number')
    ->orderBy('event_date', 'ASC')
    ->setParameter('start_date', $start_date) // 直接传DateTime对象,Doctrine会自动处理
    ->setParameter('end_date', $end_date);

补充说明:

  • DAYOFWEEK函数在DQL中是支持的,返回值1代表周日,7代表周六(和MySQL一致)
  • 如果你的eventDate是字符串类型而非DateTime,那可以保留STR_TO_DATE(r.eventDate, '%Y-%m-%d'),但更建议在实体映射时把字段类型设为datetime,避免额外转换

方案二:使用原生SQL查询(复杂场景可选)

如果需要完全使用原生MySQL语法,可以直接创建原生查询,绕过DQL的语法限制:

$sql = "
    SELECT 
        COUNT(r.id) as events_amount,
        MAX(r.eventDate) AS event_date,
        DATE(DATE_ADD(r.eventDate, INTERVAL(1 - DAYOFWEEK(r.eventDate)) DAY)) as start_of_week,
        DATE(DATE_ADD(r.eventDate, INTERVAL(7 - DAYOFWEEK(r.eventDate)) DAY)) as end_of_week,
        WEEK(STR_TO_DATE(r.eventDate, '%Y-%m-%d')) as week_number
    FROM your_table_name r
    WHERE STR_TO_DATE(r.eventDate, '%Y-%m-%d') BETWEEN :start_date AND :end_date
    GROUP BY week_number
    ORDER BY event_date ASC
";

$connection = $this->getEntityManager()->getConnection();
$stmt = $connection->prepare($sql);
$stmt->execute([
    'start_date' => $start_date->format('Y-m-d'),
    'end_date' => $end_date->format('Y-m-d')
]);
$result = $stmt->fetchAllAssociative();

(注意替换your_table_name为你的实体对应的数据库表名)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:50:08