从多对多关系中获取数据
Posted
技术标签:
【中文标题】从多对多关系中获取数据【英文标题】:Fetching data from many to many relationship 【发布时间】:2021-08-20 00:21:15 【问题描述】:我有 3 张桌子
category | case | cost | ||
---|---|---|---|---|
office_id | ||||
category_id | linked to > | category_id | ||
case_number | linked to > | case_number | ||
total_cost |
问题: 我需要获取类别表中每个办公室 ID 的案例总数及其各自的成本
我写的查询:
select cm_c_d.case_number,cm_c.office_id,count(*) as case_count from categories as cm_c
join case as cm_c_d on cm_c.category_id = cm_c_d.category_id
join cost on cm_c_d.case_number = cost.case_number group by office_id;
但我认为这不会提供所需的结果,因为加入所有三个表会增加行数。
更新的 SQL 查询:
select cm_c.office_id
, count(DISTINCT cm_costs.case_number) as case_count
, SUM(total_charge) AS overall_cost
from cm_categories as cm_c
JOIN cm_case_details as cm_c_d
on cm_c.category_id = cm_c_d.category_id
join cm_costs
on cm_c_d.case_number = cm_costs.case_number
group by cm_c.office_id
;
【问题讨论】:
我认为您还没有测试过查询,但如果您测试过,您确定可以使用名为CASE
的表而不用反引号括起来吗?据我所知CASE
是reserved word in mysql,在MySQL 查询中使用它而不用反引号将返回错误:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'case'
如果您更新我提供的插入语句(用于导致问题的特殊数据)的小提琴、真实表等,请在此处发布更新的 URL 以供审核,如果您无法。我已经用你调整的 SQL 发布了一个编辑,等待批准。
更新 fiddle 仅包含少量数据,例如:dbfiddle.uk/…
【参考方案1】:
如果您想要不同的案例计数(使用新表名进行调整):
SELECT cm_c.office_id
, COUNT(DISTINCT cm_costs.case_number) AS case_count
, SUM(total_charge) AS overall_cost
FROM cm_categories AS cm_c
JOIN cm_case_details AS cm_c_d ON cm_c.category_id = cm_c_d.category_id
JOIN cm_costs ON cm_c_d.case_number = cm_costs.case_number
GROUP BY cm_c.office_id
;
COUNT(DISTINCT x)
表示计算每个组的不同 x 值的数量。
还请注意,我们需要引用 case
表名。如前面的 cmets 所述,这是一个保留字。我建议避免使用保留字作为标识符(表、列等名称)。
我已从您的 SELECT
列表中删除了 case_number,因为它在功能上不依赖于 GROUP BY
条款。这意味着设计/查询不保证每个 office_id 最多有一个 case_number。
如果您想在选择列表中添加 case_number,则需要使用聚合形式(如 COUNT
),如下所示:
SELECT cm_c.office_id
, COUNT(DISTINCT cm_costs.case_number) AS case_count
, SUM(total_charge) AS overall_cost
, MIN(cost.case_number) AS some_case_number
, GROUP_CONCAT(cost.case_number) AS all_cases
FROM cm_categories AS cm_c
JOIN cm_case_details AS cm_c_d ON cm_c.category_id = cm_c_d.category_id
JOIN cm_costs ON cm_c_d.case_number = cm_costs.case_number
GROUP BY cm_c.office_id
;
对于非常大的集合,请注意 GROUP_CONCAT
,因为结果列的宽度可能会变得相当宽。
这是测试用例,进行了必要的调整:
Test case
有关GROUP BY
和functional dependence
的更多详细信息,请参阅以下链接:
group-by-handling
group-by-functional-dependence
【讨论】:
最好为这个答案添加一些解释。对你来说简单的事情对 OP/研究人员来说并不总是显而易见的 这个查询的问题在于,case 表中的记录数与此查询提供的记录数不同,因为它只考虑类别表中的那些行。例如:可能是类别表中只有一行 id 为 1 的类别,但在案例表中它有 5 行,并且此查询正在跳过该场景。 @ArunSharma 您在逻辑中使用了inner join
s。如果您想要与某些表中没有匹配项的项目关联的结果,则需要outer join
行为。您能否提供一些与任何特殊情况和预期结果相关的测试数据?随意更改我提供的小提琴。以上是关于从多对多关系中获取数据的主要内容,如果未能解决你的问题,请参考以下文章