【问题标题】:Dynamic Pivot MYSQL incomplete SQLDynamic Pivot MYSQL 不完整的SQL
【发布时间】:2017-10-17 07:33:20
【问题描述】:

我在一个已经工作了大约 5 周的项目上遇到了麻烦,我在此过程中发布了各种 stackoverflow 帖子,而且我几乎处于最后的障碍。

我在搜索每周总和时遇到重复数据的问题,但我似乎已经弄清楚了,但现在我的声明没有完成。 参考: Weekly Sum Dynamic Pivot MYSQL

这是一个数据。 http://sqlfiddle.com/#!9/a3610

$period = 'YEARWEEK';


    $sql = "
    SELECT
      GROUP_CONCAT(DISTINCT
        CONCAT(
          'SUM(CASE WHEN (".$period."(date)) = ',
          (".$period."(date)),
          ' THEN AMOUNT else 0 END) AS `',
          (".$period."(date)),
          '`'
        )
      ORDER BY date ASC ) AS `pivot_columns`
    FROM record_offering
    WHERE date BETWEEN ? AND ?
    ORDER BY date ASC
";

$stmt = $pdo->prepare($sql);
$date_from = '2017-01-01';
$date_to   = '2017-10-01';
$stmt->execute([$date_from, $date_to]);
$row = $stmt->fetch();
$stmt->closeCursor();
$pivot_columns = $row['pivot_columns'];

$sql = "
    SELECT title AS `Service`, {$pivot_columns}
    from record_offering t1
    join setting_service ON t1.service_id = setting_service.id
    WHERE t1.date BETWEEN ? AND ?
    GROUP BY title asc WITH ROLLUP
";

$stmt = $pdo->prepare($sql);
$stmt->execute([$date_from, $date_to]);
$results = $stmt->fetchAll();
$stmt->closeCursor();

如你所见,最后一条语句是不完整的:

SELECT title AS `Service`, SUM(CASE WHEN (YEARWEEK(date)) = 201635 THEN AMOUNT else 0 END) AS `201635`,
SUM(CASE WHEN (YEARWEEK(date)) = 201703 THEN AMOUNT else 0 END) AS `201703`,
SUM(CASE WHEN (YEARWEEK(date)) = 201709 THEN AMOUNT else 0 END) AS `201709`,
SUM(CASE WHEN (YEARWEEK(date)) = 201713 THEN AMOUNT else 0 END) AS `201713`,
SUM(CASE WHEN (YEARWEEK(date)) = 201715 THEN AMOUNT else 0 END) AS `201715`,
SUM(CASE WHEN (YEARWEEK(date)) = 201717 THEN AMOUNT else 0 END) AS `201717`,
SUM(CASE WHEN (YEARWEEK(date)) = 201718 THEN AMOUNT else 0 END) AS `201718`,
SUM(CASE WHEN (YEARWEEK(date)) = 201722 THEN AMOUNT else 0 END) AS `201722`,
SUM(CASE WHEN (YEARWEEK(date)) = 201723 THEN AMOUNT else 0 END) AS `201723`,
SUM(CASE WHEN (YEARWEEK(date)) = 201725 THEN AMOUNT else 0 END) AS `201725`,
SUM(CASE WHEN (YEARWEEK(date)) = 201726 THEN AMOUNT else 0 END) AS `201726`,
SUM(CASE WHEN (YEARWEEK(date)) = 201735 THEN AMOUNT else 0 END) AS `201735`,
SUM(CASE WHEN (YEARWEEK(date)) = 201736 THEN AMOUNT else 0 END) AS `201736`,
SUM(CASE WHEN (YEARWEEK(date)) = 201
from record_offering t1
join setting_service ON t1.service_id = setting_service.id
WHERE t1.`date` BETWEEN ? AND ?
GROUP BY title asc WITH ROLLUP

我尝试过以各种方式转义查询,但要么查询完成,我的数据被复制,要么根本无法编译。

【问题讨论】:

  • 认真考虑处理应用代码中数据显示的问题。它将大大简化此查询。在我看来,您目前的策略完全是从头到尾
  • 我最初的尝试只是一个基本的总和和组查询,然后我使用 php 对其进行了转换,但它不会正确聚合过去每天的数据。然后我被建议尝试枢轴
  • 当表示层代码可用时,我只是看不到以这种方式旋转数据的意义。
  • 还有很长的路要走,谢谢你的建议。

标签: php mysql


【解决方案1】:

GROUP_CONCAT 限制为 1024 个字节。

使用

SET SESSION group_concat_max_len = @@max_allowed_packet

在 GROUP_CONCAT 查询之前。

【讨论】:

  • 不知道,目前这个项目是在共享主机上运行的,我相信我需要root权限才能做到这一点?
  • @Enoch S 否您可以在没有超级权限或没有 root 访问权限的情况下使用此设置
【解决方案2】:

在我看来,这个(或类似的东西)是解决这个问题所需的全部 sql。 其他的一切都可以而且应该在表示层中处理。

SELECT YEARWEEK(x.date) yw
     , x.title
     , COALESCE(SUM(y.amount),0) total
  FROM setting_service x
  LEFT
  JOIN record_offering y
    ON y.service_id = x.id
 GROUP 
    BY yw
     , x.id;

【讨论】:

  • 我最初的努力正如你所说。这是我在 SA 上发布的问题:stackoverflow.com/questions/45267138/…
  • 我认为这看起来是一种更好的方法。唯一的问题是“ROLLUP” - 您可以使用一些 javascript 轻松完成。
  • 本可以完成,但问题是它没有正确聚合数据。 phpwin.org/s/0xFWpF 是小提琴。如果您将 thead 和 tbody 间隔更改为 +1 天,则数据是正确的,但在 +1 周它不会聚合,因为第一个应该是 5
猜你喜欢
  • 1970-01-01
  • 2015-11-10
  • 2014-12-30
  • 2014-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多