mysql 选择具有总风险的测试结果

bf1o4zei  于 5个月前  发布在  Mysql
关注(0)|答案(1)|浏览(59)

使用者:

id | name | age
1  | John | 20
2  | Doe  | 30

字符串
测试:

id | name
1  | Test 1
1  | Test 2


结果如下:

id | result | user_id | test_id
1  | 70     | 1       | 1
2  | 80     | 1       | 2
3  | 60     | 2       | 1
4  | 76     | 2       | 2


风险:

id | risk | min_result | max_result | age | test_id
1  | 1    | 70         | 100        | 20  | 1
2  | 2    | 60         | 69         | 20  | 1
3  | 3    | 50         | 59         | 20  | 1
4  | 1    | 80         | 100        | 30  | 1
5  | 2    | 58         | 79         | 30  | 1
.. | ..   | ..         | ..         | ..  | ..


我想得到用户的名字,以及他在所有测试中的结果和所有测试的总风险。输出示例:

name | results | total_risk
John | 70,80   | 1


我所尝试的:

$risks = DB::table('risks')
    ->selectRaw("SUM(risk) as total_risk, age, min_result, max_result, test_id");

DB::table('users AS u')
    ->distinct()
    ->select(['name', DB::raw('GROUP_CONCAT(r.result) AS results'), 'total_risk'])
    ->join('results AS r', 'r.user_id', 'u.id')
    ->joinSub($risks, 'risks', function($q){
        $q->on('risks.test_id', 'r.test_id')
            ->on('r.result', '>=', 'risks.min_result')
            ->on('r.result', '<=', 'risks.max_result')
            ->on('risks.age', 'u.age');
    })
    ->groupBy('u.id')
    ->get();


这将导致以下查询:

SELECT DISTINCT
    `name`, GROUP_CONCAT(r.result) AS results, `total_risk`
FROM
    `users` AS `u`
        INNER JOIN
    `results` AS `r` ON `r`.`user_id` = `u`.`id`
        INNER JOIN
    (SELECT 
        SUM(risk) AS total_risk,
            age,
            min_result,
            max_result,
            test_id
    FROM
        `risks`) AS `risks` ON `risks`.`test_id` = `r`.`test_id`
        AND `r`.`result` >= `risks`.`min_result`
        AND `r`.`result` <= `risks`.`max_result`
        AND `risks`.`age` = u.age
GROUP BY `u`.`id`


问题出在获取total_risk的子查询上。如果我删除它,它会正常工作,我会得到名称和结果。
我尝试连接resultsrisks表x次,次数等于测试次数,但页面一直加载,没有输出。
如何获得total_risk
我创建了一个用于直接测试的fiddle:http://sqlfiddle.com/#!9/f74 d10/1

zphenhs4

zphenhs41#

您可以使用条件聚合来计算每个用户的总风险。

SELECT
    u.name,
    GROUP_CONCAT(r.result) AS results,
    SUM(COALESCE(ri.risk, 0)) AS total_risk
FROM
    users AS u
JOIN
    results AS r ON u.id = r.user_id
LEFT JOIN
    risks AS ri ON r.test_id = ri.test_id
        AND r.result BETWEEN ri.min_result AND ri.max_result
        AND u.age = ri.age
GROUP BY
    u.id, u.name;

字符串
此查询使用LEFT JOIN根据风险表中指定的条件连接结果表和风险表。COALESCE函数用于处理结果没有匹配风险的情况。
在SELECT子句中,GROUP_CONCAT用于连接每个用户的结果,SUM用于通过对所有测试的风险进行求和来计算总风险。这将给予您所需的输出,其中包含用户名、其结果以及所有测试的总风险。

相关问题