【发布时间】:2015-10-20 11:09:25
【问题描述】:
我正在开展一个项目,用于管理现场项目关键绩效指标 (KPI) 的提交。每个提交都附有绩效衡量 (PM),这些是在提交进入现场时决定的。
用户根据完成程度为 PM 打分。我现在正在使用所有这些数据制作一份报告。我有一个有效的查询,但它非常大而且很麻烦。我正在尝试找到一种简化它的方法。
我有一个生成 KPI 列表的查询。有了这个列表,我然后应用一些子查询和简单的数学来产生那个时期的“分数”。
有 13 个句点。分数是根据本年度已完成提交的绩效衡量标准计算的。有两种类型的提交“面板”和“程序”。
需要为每个时期的两种提交类型计算分数。然后取这些分数的平均值并计算最终分数。
最终得分称为痛苦/收获指标。我们将计算出的分数除以 100,然后乘以 0.3。如果数字小于 1,则我们从痛苦/收益中减去 1,如果数字大于 0,则分别将其加 1。
第1期不同,我们只需要计算提交的节目,见下图:
第 1 期
(
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016' //current year
AND sub.state = '2' //state 2 is complete
AND sub.period = '1'
AND pm.kpi_id = kpi.id
) AS p1
但是其他时段需要根据两种提交类型的分数:
第 2 - 12 期
CASE
WHEN
(
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3 < 0 THEN
1- ROUND((
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3, 2)
WHEN
(
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3 > 0 THEN
1+ ROUND((
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3, 2)
END
END AS p2
目前在剩余时段内重复此操作。我得到的数据很好,但查询又大又丑。最重要的是,我希望在结果的末尾有一列,为所有 13 个时期的每个 KPI 创建一个平均分数。我知道我不能引用我通过它的别名创建的列,所以目前我必须再次重复子查询才能获得这个分数。
无论如何我可以使这个查询更有效率或循环通过周期 2 - 13?
完整的查询结果如下:
查询到第 2 期
SELECT
kra.id AS id,
kra.kra_name AS name,
kra.panel_weighting AS panel_weighting,
kra.programme_weighting AS programme_weighting,
kpi.id AS id,
kpi.kpi_name AS name,
kpi.panel_weighting AS panel_weighting,
kpi.programme_weighting AS programme_weighting,
(
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '1'
AND pm.kpi_id = kpi.id
) AS p1,
CASE
WHEN (
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
) IS NULL
AND
(
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
) IS NULL
THEN NULL
ELSE
CASE
WHEN
(
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3 < 0 THEN
1- ROUND((
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3, 2)
WHEN
(
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3 > 0 THEN
1+ ROUND((
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.period = '2'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.panel = 'panel'
AND pm.kpi_id = kpi.id
), 0) +
IFNULL((
SELECT
ROUND(AVG(sp.progress), 2)
FROM `submissions` AS sub
LEFT JOIN `sub_performancemeasures` sp ON sp.sub_id = sub.id
LEFT JOIN `performance_measures` pm ON pm.id = sp.pm_id
WHERE sub.programme = 'programme'
AND sub.submission_year = '2015/2016'
AND sub.state = '2'
AND sub.period = '2'
AND pm.kpi_id = kpi.id
), 0)/2) / 100 * 0.3, 2)
END
END AS p2
FROM `kpis` kpi
LEFT JOIN `key_reporting_areas` kra ON kra.id = kpi.kra_id
GROUP BY kpi.id
【问题讨论】:
-
如果您愿意,请考虑遵循以下简单的两步操作: 1. 如果您还没有这样做,请提供适当的 CREATE 和 INSERT 语句(和/或 sqlfiddle),以便我们可以更容易复制问题。 2. 如果您尚未这样做,请提供与步骤 1 中提供的信息相对应的所需结果集。
-
@Strawberry,请不要经常发布有关 DDL/Sample/SqlFiddle 的帖子。仅在过去的 10 天里,我就已经看到了十几次。如果您无法弄清楚或在精神上理解它,请不要。
标签: mysql