我想创建一个SQL查询,它应该根据日期范围生成列。
例如,如果日期的输入参数范围为2013-01-01
和2013-06-07
。然后查询应该在上述两个日期之间动态创建七个月的列。输出应如下所示:
data
column1
column2
Jan-13
feb-13
mar-13
apr-13
may-13
jun-13
{{ 1}}
我已经尝试了几次但未达到预期效果。
请分享您的想法。我该怎么办?
jul-13
因为我无法粘贴整个代码。
答案 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
基本上,我们为每个月/每年提供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;
我的示例显然比您提供的代码段简单得多,但您应该能够将逻辑重新合并到查询中。根据您打电话的方式,您也可以考虑使用存储过程。最后,这里是一篇文章的链接,该文章讨论了MySQL的 pivot 函数。