2017-07-05 36 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

相關問題