creating column alias using function in mysql?

久未见 提交于 2021-02-08 04:07:40

问题


I have this table

sales(productid, sales_date)

I want to get the monthly sales count for last 12 month.

How can I generate the month name on the column alias (without hard coding)?

I tried this :-

http://sqlfiddle.com/#!2/ee777/9

But I want the result table in this format

productid   Oct-12  Nov-12  Dec-12  Jan-13  Feb-13  Mar-13  Apr-13  May-13
1           0       0       3       4       2       8       2       11      
2           0       5       6       8       2       0       0       0   

I tried to give the column alias using function DATE_FORMAT(sales_date, '%M') but it is syntax error.

select productid,sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 12 month),'%Y%m'),1,0)) 
`12 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 11 month),'%Y%m'),1,0)) 
`11 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 10 month),'%Y%m'),1,0)) 
`10 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 9 month),'%Y%m'),1,0)) 
`9 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 8 month),'%Y%m'),1,0)) 
`8 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 7 month),'%Y%m'),1,0)) 
`7 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 6 month),'%Y%m'),1,0)) 
`6 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 5 month),'%Y%m'),1,0)) 
`5 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 4 month),'%Y%m'),1,0)) 
`4 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 3 month),'%Y%m'),1,0)) 
`3 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 2 month),'%Y%m'),1,0)) 
`2 Months Before`,
sum(if(DATE_FORMAT(sales_date,'%Y%m')=
DATE_FORMAT(date_sub(curdate(),interval 1 month),'%Y%m'),1,0)) 
`1 Months Before`
from sales
group by productid;

How can I get month and year as alias (eg:- Oct-12) in place of 12 Months Before , 11 Months Before and so on.


回答1:


MySql doesn't have PIVOT so you have to use conditional SUM().

There are two options:

  1. You do it manually if number of periods are finite and known beforehand
  2. You can use dynamic SQL to generate the query on the fly and then execute it

A query for option1 might look like this

SELECT productid
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201210' THEN 1 ELSE 0 END) `Oct12`
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201211' THEN 1 ELSE 0 END) `Nov12`      
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201212' THEN 1 ELSE 0 END) `Dec12`
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201301' THEN 1 ELSE 0 END) `Jan13`
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201302' THEN 1 ELSE 0 END) `Feb13`      
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201303' THEN 1 ELSE 0 END) `Mar13`
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201304' THEN 1 ELSE 0 END) `Apr13`
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201305' THEN 1 ELSE 0 END) `May13`      
      ,SUM(CASE WHEN DATE_FORMAT(sales_date, '%Y%m') = '201306' THEN 1 ELSE 0 END) `Jun13`
 FROM sales
WHERE sales_date BETWEEN '2012-10-01' AND '2013-06-30'
GROUP BY productid

Sample output:

| PRODUCTID | OCT12 | NOV12 | DEC12 | JAN13 | FEB13 | MAR13 | APR13 | MAY13 | JUN13 |
-------------------------------------------------------------------------------------
|         1 |     0 |     0 |     0 |     1 |     1 |     0 |     0 |     2 |     1 |
|         2 |     1 |     1 |     1 |     0 |     0 |     1 |     1 |     1 |     2 |

Here is SQLFiddle demo


Now a version for option 2 using dynamic SQL (PREPARE, EXECUTE)
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'SUM(CASE WHEN DATE_FORMAT(sales_date, ''%Y%m'') = ''',
      DATE_FORMAT(period, '%Y%m'), ''' THEN 1 ELSE 0 END) `', DATE_FORMAT(period, '%b%y'), '`'
    )
  ) INTO @sql
FROM
(
    SELECT DATE_FORMAT(sales_date, '%Y-%m-01') period
      FROM sales
     WHERE sales_date BETWEEN DATE_FORMAT(CURDATE() - INTERVAL 11 MONTH, '%Y-%m-01') AND CURDATE()
     GROUP BY DATE_FORMAT(sales_date, '%Y-%m-01')
) s;

SET @sql = CONCAT
('SELECT productid, ', @sql, ' 
    FROM sales
   WHERE sales_date BETWEEN DATE_FORMAT(CURDATE() - INTERVAL 11 MONTH, ''%Y-%m-01'') AND CURDATE()
   GROUP BY productid'
);

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

Output is the same.

| PRODUCTID | JUL12 | AUG12 | SEP12 | OCT12 | NOV12 | DEC12 | JAN13 | FEB13 | MAR13 | APR13 | MAY13 | JUN13 |
-------------------------------------------------------------------------------------------------------------
|         1 |     1 |     2 |     1 |     0 |     0 |     0 |     1 |     1 |     0 |     0 |     2 |     1 |
|         2 |     0 |     0 |     0 |     1 |     1 |     1 |     0 |     0 |     1 |     1 |     1 |     2 |

Here is SQLFiddle demo



来源:https://stackoverflow.com/questions/17376528/creating-column-alias-using-function-in-mysql

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!