【问题标题】:sum of cases in grand-parent, parents, children,, and etc祖父母、父母、子女等的案件总和
【发布时间】:2020-07-25 21:07:59
【问题描述】:

我需要计算以下案例的总数:parent citiesdistrictsregions

那么请让我告诉你目前的情况以及我目前所做的工作


我有两张桌子[cities] & [covid19cities]


[城市] 表: 参考表

结构是:

------------------------------
| id | parent_id | city_name |
------------------------------

城市等级为:

 - Region          //[its parent_id = 0]
 -- District       //[its parent_id = the region id]
 ---- Parent-city  //[its parent_id = the district id]
 ------ Child-city //[its parent_id = the parent-city id]

[covid19cities] 表:

结构是:

-----------------------------------------------------
| id | city_id | date | n_cases | r_cases | d_cases |
-----------------------------------------------------

所以我们每天都会在[covid19cities] 填写不同城市的不同案例:

n_cases = 新的 covid-19 病例; r_cases = 康复病例; d_cases = 死亡病例


到目前为止:

  1. 我可以使用这样的查询获得每个城市的病例总数(例如新病例):

    SELECT  sum(`n_cases`) AS city_n_cases, cities.name AS city_name,
            cities.id AS city_id,
        FROM  covid19cities
        INNER JOIN  cities  ON cities.id = covid19cities.city_id
        WHERE  covid19cities.city_id = '#'
    
    1. 我能够获得所有城市的所有病例(例如新病例)的总和:
选择 sum(`n_cases`) AS total_n_cases, 从 covid19城市

现在,我需要计算以下案例的总数:

  • 母市
  • 地区
  • 地区

那么,我该如何实现呢?我想到的是

  1. 查找所有地区
  2. 在 fetch assoc while 循环中,我搜索该区域的地区
  3. 在我搜索父城市的地区的 fetch assoc while 循环中
  4. 在父城市的 fetch assoc while 循环中,我搜索子城市
  5. 计算总和,然后向后添加到父城市,然后从那里到地区,然后到区域!

但是我认为这不是应该的做法。但是,我不知道在这种情况下如何继续跟踪亲子城市。

感谢您的建议和帮助。

谢谢

p.s. sorry for my English :/

【问题讨论】:

  • 如果级别是固定的,那么 3 个自连接将为您提供层次结构,您可以使用 rollup group by 修饰符来获取父级的总和。
  • 您在表格中为城市级别准备的模型是什么,似乎没有提到您为模型分配了该关系的哪一列。或者您想在单独的表中考虑它们,然后进行相关查询!?
  • @Shadow 你能解释一下吗?
  • @sultan,我知道,但它的逻辑对读者来说并不清楚,我想说!也许你应该更详细地解释这种关系
  • @GMB,谢谢,我已经看到你的答案,我会尝试将它应用到我的系统中。如果它不起作用,我将为您提供我数据库中的示例数据。再次感谢。

标签: php mysql sql database join


【解决方案1】:

考虑以下基本查询,它为您提供每个 city_id 的每个案例类别的总和。我们可以通过查看covid19cities 来获取这些信息:

select 
    cvc.city_id,
    sum(cvc.n_cases) sum_n_cases,
    sum(cvc.r_cases) sum_r_cases,
    sum(cvc.d_cases) sum_d_cases
from covid19cities cvc
group by cvc.city_id

现在让我们带来cities 表。这给出了相同的结果,您也可以显示城市名称:

select 
    c.id   city_id,
    c.name city_name, 
    sum(cvc.n_cases) sum_n_cases,
    sum(cvc.r_cases) sum_r_cases,
    sum(cvc.d_cases) sum_d_cases
from covid19cities cvc
inner join cities c on c.id = cvc.city_id
group by c.id, c.name

从那里开始,我们可以通过在cities 表上添加更多连接并更改selectgroup by 子句中的列来逐级向上跟踪层次结构。

让我们获取每个父城市的病例数:我们第二次加入cities 表,别名为pc(父城市):

select 
    pc.id   parent_city_id,
    pc.name parent_city_name, 
    sum(cvc.n_cases) sum_n_cases,
    sum(cvc.r_cases) sum_r_cases,
    sum(cvc.d_cases) sum_d_cases
from covid19cities cvc
inner join cities c  on c.id  = cvc.city_id
inner join cities pc on pc.id = c.parent_id
group by pc.id, pc.name

下一级是

select 
    d.id   distict_id,
    d.name district_name, 
    sum(cvc.n_cases) sum_n_cases,
    sum(cvc.r_cases) sum_r_cases,
    sum(cvc.d_cases) sum_d_cases
from covid19cities cvc
inner join cities c  on c.id  = cvc.city_id
inner join cities pc on pc.id =  c.parent_id
inner join cities d  on d.id  = pc.parent_id
group by d.id, d.name

最后,这里是给出上层信息的查询,即区域:

select 
    r.id   region_id,
    r.name region_name, 
    sum(cvc.n_cases) sum_n_cases,
    sum(cvc.r_cases) sum_r_cases,
    sum(cvc.d_cases) sum_d_cases
from covid19cities cvc
inner join cities c  on c.id  = cvc.city_id
inner join cities pc on pc.id =  c.parent_id
inner join cities d  on d.id  = pc.parent_id
inner join cities r  on r.id  =  d.parent_id
group by r.id, r.name

作为一个更一般的想法:请注意,这里的复杂性来自您将分层结构存储在cities 表中的事实。使用单独的表来存储每个实体会更简单,用外键来表示关系,例如:

regions:        region_id, region_name
districts:      district_id, district_name, region_id
parent_cities:  parent_city_id, parent_city_name, district_id
cities:         city_id, city_name, parent_city_id

使用这种设计,您的最后一个查询将如下所示:

select 
    r.region_id,
    r.region_name, 
    sum(cvc.n_cases) sum_n_cases,
    sum(cvc.r_cases) sum_r_cases,
    sum(cvc.d_cases) sum_d_cases
from covid19cities cvc
inner join cities c         on c.id              = cvc.city_id
inner join parent_cities pc on pc.parent_city_id =  c.parent_city_id
inner join districts     d  on d.district_id     = pc.district_id
inner join regions       r  on r.region_id       =  d.region_id
group by r.region_id, r.region_name

这是相同数量的连接,但事物存储在不同的表中,因此查询更容易编写和阅读。

【讨论】:

    【解决方案2】:

    由于只有3个级别,而不是任意数量的级别,我建议你太努力了。有一个表格,其中包含 3 列的区域、地区和城市。每天只有几千行,因此缺乏规范化不会导致巨大的磁盘开销。

    另一方面,如果这是一个学习练习,那么请获取 MySQL 8 或 MariaDB 10.2 并了解“递归 CTE”。

    【讨论】:

      猜你喜欢
      • 2011-01-12
      • 1970-01-01
      • 2015-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多