我有一个包含日期和状态的普通表(select
result.reference_date
,sum(case when result.funnel_phase = 'signup_date' then cont else 0 end) as signup_date
,sum(case when result.funnel_phase = '01_approval_requested' then cont else 0 end) as 01_approval_requested
,sum(case when result.funnel_phase = '02_approval_allowed' then cont else 0 end) as 02_approval_allowed
,sum(case when result.funnel_phase = '03_profile_sent_documents' then cont else 0 end) as 03_profile_sent_documents
,sum(case when result.funnel_phase = '04_profile_approved' then cont else 0 end) as 04_profile_approved
,sum(case when result.funnel_phase = '05_loan_request' then cont else 0 end) as 05_loan_request
,sum(case when result.funnel_phase = '06_boleto_confirmed' then cont else 0 end) as 06_boleto_confirmed
,sum(case when result.funnel_phase = '07_loan_issued' then cont else 0 end) as 07_loan_issued
from
(
select 'signup_date' funnel_phase, month(signup_date) as reference_date, count(signup_date) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '01_approval_requested' funnel_phase, month(01_approval_requested) as reference_date, count(01_approval_requested) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '02_approval_allowed' funnel_phase, month(02_approval_allowed) as reference_date, count(02_approval_allowed) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '03_profile_sent_documents' funnel_phase, month(03_profile_sent_documents) as reference_date, count(03_profile_sent_documents) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '04_profile_approved' funnel_phase, month(04_profile_approved) as reference_date, count(04_profile_approved) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '05_loan_request' funnel_phase, month(05_loan_request) as reference_date, count(05_loan_request) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '06_boleto_confirmed' funnel_phase, month(06_boleto_confirmed) as reference_date, count(06_boleto_confirmed) as cont
from db.mkt_parceiros_2
group by 1, 2
union all
select '07_loan_issued' funnel_phase, month(07_loan_issued) as reference_date, count(07_loan_issued) as cont
from db.mkt_parceiros_2
group by 1, 2
) result
group by result.reference_date
),我必须从中创建一个数据透视表(Y轴为MM-YYYY,X轴为状态,然后在表格中为其对应的值)。
我提取同一个表七次,因为它是状态数,然后我按日期和状态对其进行分组。
它在同一张桌子上读了7次,花了很长时间。 我想知道是否有任何方法可以改善其性能。 我尝试如下:
{{1}}
答案 0 :(得分:1)
reference_date
子查询选择的所有union
字段都会返回一个月份数。
您可以使用数字表构建一个等效查询,其中包含所有12个月的值并交叉加入db.mkt_parceiros_2
:
SELECT t1.m AS reference_date,
COUNT(CASE
WHEN MONTH(signup_date) = t1.m THEN 1
END) AS signup_date,
COUNT(CASE
WHEN MONTH(01_approval_requested) = t1.m THEN 1
END) AS 01_approval_requested,
... etc
FROM (
SELECT 1 AS m UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL
SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL
SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12) AS t1
CROSS JOIN db.mkt_parceiros_2 AS t2
GROUP BY t1.m
答案 1 :(得分:0)
我的答案与Giorgos类似,但避免 CROSS 加入;是否昂贵/复杂的连接条件比CROSS JOIN快,我不能肯定地说。
SELECT theMonths.m AS reference_date
, COUNT(CASE WHEN MONTH(mpt.signup_date) = theMonths.m THEN 1 END) AS signup_date
, COUNT(CASE WHEN MONTH(mpt.`01_approval_requested`) = theMonths.m THEN 1 END) AS `01_approval_requested`
, ...
FROM (
SELECT 1 AS m
UNION SELECT 2
UNION SELECT 3
...) AS theMonths
LEFT JOIN db.mkt_parceiros_2 AS mpt
ON theMonths.m IN (
MONTH(mpt.signup_date)
, MONTH(mpt.`01_approval_requested`)
, ...
)
GROUP BY theMonths.m
;
如果您只参加特定的一年,可能会从此次更改中获得一些性能提升 ...但不太可能,因为MySQL不会/无法利用OR条件列表中的索引。
SELECT theMonths.m AS reference_date
, COUNT(CASE WHEN mpt.signup_date BETWEEN theMonths.mBegin AND theMonths.mEnd THEN 1 END) AS signup_date
, COUNT(CASE WHEN mpt.`01_approval_requested` BETWEEN theMonths.mBegin AND theMonths.mEnd THEN 1 END) AS `01_approval_requested`
, ...
FROM (
SELECT 1 AS m, '2017-01-01' AS mBegin, '2017-01-31' AS mEnd
UNION SELECT 2 , '2017-02-01', '2017-02-28' /* careful of leap year */
...) AS theMonths
LEFT JOIN db.mkt_parceiros_2 AS mpt
ON mpt.signup_date BETWEEN theMonths.mBegin AND theMonths.mEnd
OR mpt.`01_approval_requested` BETWEEN theMonths.mBegin AND theMonths.mEnd
OR ...
GROUP BY theMonths.m
;