如何获取查询的动态列

时间:2014-02-11 14:10:28

标签: mysql sql pentaho

我想创建一个SQL查询,它应该根据日期范围生成列。 例如,如果日期的输入参数范围为2013-01-012013-06-07。然后查询应该在上述两个日期之间动态创建七个月的列。输出应如下所示:

data column1 column2 Jan-13 feb-13 mar-13 apr-13 may-13 jun-13 {{ 1}}

我已经尝试了几次但未达到预期效果。

请分享您的想法。我该怎么办?

jul-13

因为我无法粘贴整个代码。

1 个答案:

答案 0 :(得分:1)

您尝试做的是将数据从行转移到列中。不幸的是,MySQL没有这种功能,但是,我们可以使用带有CASE语句的聚合函数来获得类似的结果。

SELECT
  cid,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 1 THEN total ELSE 0 END) AS JAN_13,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 2 THEN total ELSE 0 END) AS FEB_13,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 3 THEN total ELSE 0 END) AS MAR_13,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 4 THEN total ELSE 0 END) AS ARR_13,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 5 THEN total ELSE 0 END) AS MAY_13,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 6 THEN total ELSE 0 END) AS JUN_13,
  SUM(CASE WHEN YEAR(duedate) = 2013 AND MONTH(duedate) = 7 THEN total ELSE 0 END) AS JUL_13
FROM invoices
GROUP BY cid

DEMO

基本上,我们为每个月/每年提供CASE行,我们希望获得SUM。您可以为每个月/每年添加一行,并将日期范围添加回WHERE子句,但这仍会为所有月份创建列,其值为零here

动态执行此操作的更好方法是使用预准备语句。这样我们就可以在WHERE子句中提供我们的日期范围,并让SQL做繁重的工作。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'SUM(CASE WHEN MonthYear = ''',
      MonthYear,
      ''' THEN total ELSE 0 END) AS ',
      MonthYear
    )
  ) INTO @sql
FROM (
  SELECT
    cid,
    DATE_FORMAT(duedate, '%b_%y') MonthYear,
    total
  FROM invoices
  WHERE duedate BETWEEN CAST('2013-01-01' AS DATE) AND CAST('2013-07-31' AS DATE)
  ORDER BY duedate
) src;

SET @sql = CONCAT("SELECT cid, ", @sql, "
                   FROM (
                     SELECT
                       cid,
                       DATE_FORMAT(duedate, '%b_%y') MonthYear,
                       total
                     FROM invoices
                     WHERE duedate BETWEEN CAST('2013-01-01' AS DATE) AND CAST('2013-07-31' AS DATE)
                     ORDER BY duedate
                   ) src
                   GROUP BY cid");

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

DEMO

我的示例显然比您提供的代码段简单得多,但您应该能够将逻辑重新合并到查询中。根据您打电话的方式,您也可以考虑使用存储过程。最后,这里是一篇文章的链接,该文章讨论了MySQL的 pivot 函数。

Dynamic pivot tables (transform rows to columns)