сумма дел в прародителях, родителях, детях и т. д. - PullRequest
1 голос
/ 13 апреля 2020

Мне нужно подсчитать общее количество дел по: parent cities, districts и regions

Итак, позвольте мне рассказать вам, какова ситуация и что я до сих пор сделали


У меня есть две таблицы [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 = новые случаи из 19 covid; 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 = '#'
    
  2. Я могу получить сумму всех дел (например, новых дел) во всех городах:
SELECT 
sum(`n_cases`) AS total_n_cases, 
FROM 
covid19cities 

Сейчас, мне нужно подсчитать общее количество дел по:

  • родительским городам
  • округам
  • регионам

Итак, как могу ли я сделать это 1105 *? Я подумал о

  1. , чтобы найти все регионы
  2. в пределах выборки ассо c, в то время как -l oop Я ищу районы этого региона
  3. в пределах выборки ассо c while-l oop районов, которые я ищу, для родительских городов
  4. в пределах выборки ассо c while-l oop из родительских городов, которые я ищу детские города
  5. подсчитывают сумму, а затем добавляют обратно в родительские города и оттуда в районы, а затем в регионы!

НО Я считаю, это не так, как это должно быть сделано. Тем не менее, я не знаю, как следить за городами-родителями в таком случае.

Я ценю ваши советы и помощь.

Спасибо

p.s. sorry for my English :/

Ответы [ 2 ]

2 голосов
/ 17 апреля 2020

Рассмотрим следующий базовый запрос, который дает вам сумму каждой категории дел на 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 и изменение столбцов в предложениях select и group 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

Это такое же количество объединений, но вещи хранятся в разных таблицах, поэтому запрос гораздо проще писать и читать.

1 голос
/ 19 апреля 2020

Поскольку существует только 3 уровня, а не произвольное количество уровней, я полагаю, что вы слишком усердно работаете. В таблице указывается одна таблица с 3 столбцами для региона, района и города. Это всего несколько тысяч строк в день, поэтому отсутствие нормализации не приведет к огромным затратам на диск.

Если, с другой стороны, это учебное упражнение, тогда получите MySQL 8 или MariaDB 10.2 и узнайте о «рекурсивных CTE».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...