2017-07-05 34 views
1

我有名为user_plan_dtl的表,其中包含用户标识列,计划描述和联系日期。根据计划描述,我希望每个月都有用户数。月份只能在给定的日期范围内选择。 我在mysql中有数据库。如何在mysql查询中使用crosstab或pivote来获取月份名称dynamicaly?

下面是桌子user_plan_dtl

userid  contactdate plandesc 
USR001   March  ICMA 
USR003   March  ICMA 
USR004   April  FTDA 
USR005   April  FTDA 
USR006   April  FTDA 
USR007   April  ICMA 
USR008   April  ICMA 
USR009   May   FTDA 
USR002   May   FTDA 
USR001   May   ICMA 

我想输出,如:

Count March April May 
Total  2  5  3 
FTDA  0  3  2 
ICMA  2  2  1 

我试图与下面的查询,但我得到的输出所有月份。

select d.Plandesc as AssignedUsers, max(d.January) as January,max(d.February) as February,max(d.March) as March, 
max(d.April) as April ,max(d.May)as May,max(d.June)as June, 
max(d.July) as July,max(d.August)as August,max(d.September) as September, 
max(d.October)as October,max(d.November) as November ,max(d.December)as December from 
(Select Plandesc, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='January' THEN userid END)) AS January, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='February' THEN userid END)) AS February, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='March' THEN userid END)) AS March, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='April' THEN userid END)) AS April, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='May' THEN userid END)) AS May, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='June' THEN userid END)) AS June, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='July' THEN userid END)) AS July, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='August' THEN userid END)) AS August, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='September' THEN userid END)) AS September, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='October' THEN userid END)) AS October, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='November' THEN userid END)) AS November, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='December' THEN userid END)) AS December 
from user_plan_dtl 
where Plandesc in ('FTDA','ICMA') 
and DATE_FORMAT(contactdate, '%Y-%m-%d') >= '2017-01-01' and DATE_FORMAT(contactdate, '%Y-%m-%d') <= '2017-07-05' 
group by MONTHNAME(contactdate),Plandesc 
union all 
Select 'Total' as Plandesc, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='January' THEN userid END)) AS January, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='February' THEN userid END)) AS February, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='March' THEN userid END)) AS March, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='April' THEN userid END)) AS April, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='May' THEN userid END)) AS May, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='June' THEN userid END)) AS June, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='July' THEN userid END)) AS July, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='August' THEN userid END)) AS August, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='September' THEN userid END)) AS September, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='October' THEN userid END)) AS October, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='November' THEN userid END)) AS November, 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)='December' THEN userid END)) AS December 
from user_plan_dtl 
where Plandesc in ('FTDA','ICMA') 
and DATE_FORMAT(contactdate, '%Y-%m-%d') >= '2017-01-01' and DATE_FORMAT(contactdate, '%Y-%m-%d') <= '2017-07-05' 
group by MONTHNAME(contactdate) 
) as d group by d.Plandesc order by case when d.Plandesc = 'Total' then 0 else 1 end,d.Plandesc 

任何人都可以为我提供解决方案吗?提前致谢。

回答

1

我想出了这个解决方案,设置变量和使用预处理语句:

DROP TABLE IF EXISTS user_plan_temp; 

SET @JanTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='January'); 
SET @FebTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='February'); 
SET @MarTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='March'); 
SET @AprTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='April'); 
SET @MayTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='May'); 
SET @JunTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='June'); 
SET @JulTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='July'); 
SET @AugTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='August'); 
SET @SepTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='September'); 
SET @OctTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='October'); 
SET @NovTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='November'); 
SET @DecTotal = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc IN ('FTDA','ICMA') AND MONTHNAME(contactdate)='December'); 

SET @SQLq = 'CREATE TEMPORARY TABLE user_plan_temp AS (SELECT "Total" AS Count '; 
SET @SQLq = CONCAT(@SQLq, IF(@JanTotal > 0, ', @JanTotal AS January','')); 
SET @SQLq = CONCAT(@SQLq, IF(@FebTotal > 0, ', @FebTotal AS February','')); 
SET @SQLq = CONCAT(@SQLq, IF(@MarTotal > 0, ', @MarTotal AS March','')); 
SET @SQLq = CONCAT(@SQLq, IF(@AprTotal > 0, ', @AprTotal AS April','')); 
SET @SQLq = CONCAT(@SQLq, IF(@MayTotal > 0, ', @MayTotal AS May','')); 
SET @SQLq = CONCAT(@SQLq, IF(@JunTotal > 0, ', @JunTotal AS June','')); 
SET @SQLq = CONCAT(@SQLq, IF(@JulTotal > 0, ', @JulTotal AS July','')); 
SET @SQLq = CONCAT(@SQLq, IF(@AugTotal > 0, ', @AugTotal AS August','')); 
SET @SQLq = CONCAT(@SQLq, IF(@SepTotal > 0, ', @SepTotal AS September','')); 
SET @SQLq = CONCAT(@SQLq, IF(@OctTotal > 0, ', @OctTotal AS October','')); 
SET @SQLq = CONCAT(@SQLq, IF(@NovTotal > 0, ', @NovTotal AS November','')); 
SET @SQLq = CONCAT(@SQLq, IF(@DecTotal > 0, ', @DecTotal AS December','')); 
SET @SQLq = CONCAT(@SQLq, ')'); 
PREPARE stmt1 FROM @SQLq; 
EXECUTE stmt1; 
DEALLOCATE PREPARE stmt1; 
-- SELECT * FROM user_plan_temp; 

SET @SQLq2 = 'INSERT INTO user_plan_temp VALUES("FTDA" '; 
SET @JanFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='January'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@JanTotal > 0, ', @JanFTDA','')); 
SET @FebFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='February'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@FebTotal > 0, ', @FebFTDA','')); 
SET @MarFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='March'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@MarTotal > 0, ', @MarFTDA','')); 
SET @AprFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='April'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@AprTotal > 0, ', @AprFTDA','')); 
SET @MayFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='May'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@MayTotal > 0, ', @MayFTDA','')); 
SET @JunFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='June'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@JunTotal > 0, ', @JunFTDA','')); 
SET @JulFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='July'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@JulTotal > 0, ', @JulFTDA','')); 
SET @AugFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='August'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@AugTotal > 0, ', @AugFTDA','')); 
SET @SepFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='September'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@SepTotal > 0, ', @SepFTDA','')); 
SET @OctFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='October'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@OctTotal > 0, ', @OctFTDA','')); 
SET @NovFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='November'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@NovTotal > 0, ', @NovFTDA','')); 
SET @DecFTDA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'FTDA' AND MONTHNAME(contactdate)='December'); 
SET @SQLq2 = CONCAT(@SQLq2, IF(@DecTotal > 0, ', @DecFTDA','')); 
SET @SQLq2 = CONCAT(@SQLq2, ')'); 
-- SELECT @SQLq2; 
PREPARE stmt2 FROM @SQLq2; 
EXECUTE stmt2; 
DEALLOCATE PREPARE stmt2; 

SET @SQLq3 = 'INSERT INTO user_plan_temp VALUES("FTDA" '; 
SET @JanICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='January'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@JanTotal > 0, ', @JanICMA','')); 
SET @FebICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='February'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@FebTotal > 0, ', @FebICMA','')); 
SET @MarICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='March'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@MarTotal > 0, ', @MarICMA','')); 
SET @AprICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='April'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@AprTotal > 0, ', @AprICMA','')); 
SET @MayICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='May'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@MayTotal > 0, ', @MayICMA','')); 
SET @JunICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='June'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@JunTotal > 0, ', @JunICMA','')); 
SET @JulICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='July'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@JulTotal > 0, ', @JulICMA','')); 
SET @AugICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='August'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@AugTotal > 0, ', @AugICMA','')); 
SET @SepICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='September'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@SepTotal > 0, ', @SepICMA','')); 
SET @OctICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='October'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@OctTotal > 0, ', @OctICMA','')); 
SET @NovICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='November'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@NovTotal > 0, ', @NovICMA','')); 
SET @DecICMA = (Select COUNT(DISTINCT(userid)) from user_plan_dtl WHERE plandesc = 'ICMA' AND MONTHNAME(contactdate)='December'); 
SET @SQLq3 = CONCAT(@SQLq3, IF(@DecTotal > 0, ', @DecICMA','')); 
SET @SQLq3 = CONCAT(@SQLq3, ')'); 
PREPARE stmt3 FROM @SQLq3; 
EXECUTE stmt3; 
DEALLOCATE PREPARE stmt3; 

SELECT * FROM user_plan_temp; 
+1

谢谢你这么多TBowman,非常感谢...这个解决方案工作完美....只有我所做的改变是,在SET @ SQLq3 ='INSERT INTO user_plan_temp VALUES(“FTDA”'; .... ...而不是FTDA它应该是ICMA,因为我们为ICMA插入了值。无论如何你节省了我很多时间,再次感谢。 – Madhura

2

使用CONCATGROUP_CONCAT来构造复杂的查询。

set @sql=NULL; 
select group_concat(distinct concat(
    ' COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)="',c_month, 
    '" THEN userid END)) AS "',c_month,'"') separator ',') 
    from (select distinct contactdate as c_month from user_plan_dtl) t into @sql; 
select @sql; 

(请注意,我用contactdate从你这里张贴在一个月的数据,而不是作为一个日期)

这将使你在变量@sql的字符串:

COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)="March" THEN userid END)) 
    AS "March", 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)="April" THEN userid END)) 
    AS "April", 
COUNT(DISTINCT(CASE WHEN MONTHNAME(contactdate)="May" THEN userid END)) 
    AS "May" 

然后你就可以操纵这个字符串

set @sql=concat('SELECT ',@sql); 
select @sql; 

等。 (提示:为整个陈述创建另一个变量,并将其与@sql连接)。最后你要准备和执行这条SQL语句:

PREPARE stmnt from @sql; 
EXECUTE stmnt; 
DEALLOCATE stmnt; 
+0

嘿Michael..thanks的评论,但在这里你已使用三月,四月和五月硬编码。我想动态地。 – Madhura

+0

它们不是“硬编码的”,它们来自您的表格,只需使用'select distinct monthname(contactdate)as c_month'。你甚至读过答案吗? –

+0

对不起...现在我得到了答案,我认为这会比上面的更快,但我没有得到你提到的提示....(提示:为整个陈述创建另一个变量,并将其与@sql),请你详细说明一下。 – Madhura

相关问题