我已经看到了一些相关的问题,但他们似乎并没有相同的情况,所以请帮助。
我有当前的查询:
SELECT
COUNT(CASE WHEN training_enhancments.reason_id = 0 THEN 1 END) AS '0Count',
COUNT(CASE WHEN training_enhancments.reason_id = 1 THEN 1 END) AS '1Count',
COUNT(CASE WHEN training_enhancments.reason_id = 2 THEN 1 END) AS '2Count',
COUNT(CASE WHEN training_enhancments.reason_id = 3 THEN 1 END) AS '3Count',
COUNT(CASE WHEN training_enhancments.reason_id = 8 THEN 1 END) AS '4Count',
...
COUNT(CASE WHEN training_enhancments.reason_id = 40 THEN 1 END) AS '40Count',
FROM
claims claims
INNER JOIN users users ON claims.surveyor_id = users.user_id
INNER JOIN insurers insurers on claims.insurer_id = insurers.insurer_id
LEFT JOIN training_enhancments training_enhancments on claims.claim_id = training_enhancments.claim_id
WHERE
claims.claim_cancelled_id <= 0 AND
claims.date_completed BETWEEN '2014-10-01 00:00:00' AND '2014-10-31 23:59:59'
GROUP BY claims.surveyor_id;
如何重写COUNT()语句以提高效率/可读性?类似for / while循环的东西,但我不确定它们是否存在于SQL中。
感谢。
答案 0 :(得分:0)
尝试按training_enhancments.reason_id
分组,然后在您的应用程序代码中,您可以使用for / while循环显示40个计数。
SELECT
claims.surveyor_id,
training_enhancments.reason_id,
COUNT(*)
FROM
claims claims
INNER JOIN users users ON claims.surveyor_id = users.user_id
INNER JOIN insurers insurers on claims.insurer_id = insurers.insurer_id
LEFT JOIN training_enhancments training_enhancments on claims.claim_id = training_enhancments.claim_id
WHERE
claims.claim_cancelled_id <= 0 AND
claims.date_completed BETWEEN '2014-10-01 00:00:00' AND '2014-10-31 23:59:59'
GROUP BY
claims.surveyor_id,
training_enhancments.reason_id;
答案 1 :(得分:0)
如果您需要在单独的列中进行此操作,则不会提高效率。但是,在MySQL中,您可以使用布尔表达式,结果为1表示true,0表示false,从而使其更具可读性:
SELECT
SUM(training_enhancments.reason_id = 0) AS '0Count',
SUM(training_enhancments.reason_id = 1) AS '1Count',
...
FROM ...
答案 2 :(得分:0)
如果每个测量员ID需要一行并且有固定列,那么您当前的解决方案非常好。
如果每个Surveyor id可以有多行,并且可以在调用脚本中处理它们,那么Jaugar Chang的解决方案将是我的选择。
如果您必须为每个测量员ID返回一行,但可以将返回行中的字段拆分为各种计数,那么您可以执行以下操作: -
SELECT surveyor_id, GROUP_CONCAT(CONCAT_WS(':', reason_id, reason_count))
(
SELECT claims.surveyor_id, training_enhancments.reason_id, COUNT(*) AS reason_count
FROM claims claims
INNER JOIN users users ON claims.surveyor_id = users.user_id
INNER JOIN insurers insurers on claims.insurer_id = insurers.insurer_id
LEFT JOIN training_enhancments training_enhancments on claims.claim_id = training_enhancments.claim_id
WHERE claims.claim_cancelled_id <= 0
AND claims.date_completed BETWEEN '2014-10-01 00:00:00' AND '2014-10-31 23:59:59'
GROUP BY claims.surveyor_id, training_enhancments.reason_id
) sub0
GROUP BY surveyor_id;
或者为测量员强制设置所有原因ID的值(即使没有用于该测量员): -
SELECT surveyor_id, GROUP_CONCAT(CONCAT_WS(':', reason_id, reason_count))
(
SELECT claims.surveyor_id, reasons.reason_id, COUNT(training_enhancments.claim_id) AS reason_count
FROM claims claims
CROSS JOIN (SELECT 0 AS reason_id UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 8 UNION SELECT 40) reasons
INNER JOIN users users ON claims.surveyor_id = users.user_id
INNER JOIN insurers insurers on claims.insurer_id = insurers.insurer_id
LEFT JOIN training_enhancments training_enhancments on claims.claim_id = training_enhancments.claim_id
WHERE claims.claim_cancelled_id <= 0
AND claims.date_completed BETWEEN '2014-10-01 00:00:00' AND '2014-10-31 23:59:59'
GROUP BY claims.surveyor_id, training_enhancments.reason_id
) sub0
GROUP BY surveyor_id;
答案 3 :(得分:0)
最后,我在周围的语言PHP中进行了for循环。
更具可读性吗?值得商榷。然而,扩展它当然更容易。
$numReasons = 38;
$SQL = "SELECT CONCAT(users.user_first_name,IF((users.user_surname<>''),CONCAT(' ',users.user_surname),'')) as 'Surveyor'";
for ($i = 0; $i < $numReasons + 1; $i++) {
$SQL .= ", COUNT(CASE WHEN training_enhancments.reason_id = $i THEN 1 END) AS '" . $i . "Count' ";
}
$SQL .= "FROM
claims claims
INNER JOIN users users ON claims.surveyor_id = users.user_id
INNER JOIN insurers insurers on claims.insurer_id = insurers.insurer_id
LEFT JOIN training_enhancments training_enhancments on claims.claim_id = training_enhancments.claim_id