Соедините две таблицы и правильно сгруппируйте результаты - PullRequest
1 голос
/ 18 октября 2019

Я использую базу данных SQL для хранения некоторых людей, считающих результаты анализа видео. Таблицу count можно суммировать следующим образом:

rowid (auto increment int)  |     created_at (date)   |   type (int)  | count_value (int)
----------------------------+-------------------------+---------------+-------------

Позже я хотел добавить некоторые атрибуты для обнаруженных людей, все еще используя обработку изображений. Я мог бы изменить таблицу counting , но для каждого добавленного атрибута мне пришлось бы вручную изменять таблицу counting . Я хотел динамическое решение. Была создана вторая таблица, которая называется attribute , что довольно просто.

rowid (auto increment int)  |     key (string)   |   value (string)  | row_id_counting (int)
----------------------------+--------------------+-------------------+-------------

Например, если мой алгоритм обнаружит 30-летнего мужчину, в появятся следующие строкиподсчет и атрибутов таблиц:

COUNTING :

rowid |     created_at    | type | count_value 
------+-------------------+------+-------------
 150  | 2019.10.18  08:50 |  1   |      1


ATTRIBUTES :

rowid  |     key   |   value  | row_id_counting
-------+-----------+----------+---------------
  120  | "gender"  |  "M"     |      150 
  121  |  "age"    |  "30"    |      150

Если когда-нибудь в моей подсчет таблице придется хранить данные другого типа (например, о кошках или транспортных средствах), яможно указать его в столбце type, и мне не придется хранить бесполезные атрибуты для этих данных, поскольку атрибуты хранятся в другой таблице и создаются динамически.

Я также могу легко получить некоторые данные из подсчет с определенными атрибутами с использованием JOIN в моих запросах SQL.


Теперь я хочу суммировать все данные с одинаковыми атрибутами в час, чтобы создать некоторую статистику из моеготаблица подсчетаМое первое решение:

SELECT SUM(count_value), attr.key, attr.value, strftime('%Y-%m-%d %H:00:00',created_at, 'localtime') as timestr 
    FROM counting cnt 
    LEFT JOIN attributes attr ON cnt.rowid = attr.row_id_counting
    WHERE datetime(created_at,'localtime') BETWEEN '2019-10-16 22:00:0.000000' AND '2019-10-17 22:00:00.000000' 
    AND cnt.type = 1
    GROUP BY timestr,attr.key, attr.value

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

  • Один 50-летний человек, неизвестный пол
  • Один 20-летний мужчина
  • Одна женщина, неизвестный возраст
  • Один человек, неизвестный возраст и пол

Результаты:

 SUM(count_value)   key       value       timestr
 1                  (null)    (null)      2019-10-18 10:00:00
 1                  age       20          2019-10-18 10:00:00
 1                  age       50          2019-10-18 10:00:00
 1                  gender    F           2019-10-18 10:00:00
 1                  gender    M           2019-10-18 10:00:00

Даже если я добавлю (нулевую) (нулевую) строку всуммы возрастных или гендерных атрибутов, я считаю только 3 человека вместо 4. Пропавшим человеком по возрастной сумме является женщина с неизвестным возрастом, а пропавшим по гендерной сумме - 50 лет с неизвестным полом.

Есть ли способ изменить этот запрос SQL, чтобы вместо него были следующие строки:

 SUM(count_value)   key       value       timestr
 2                  age       (null)      2019-10-18 10:00:00
 1                  age       20          2019-10-18 10:00:00
 1                  age       50          2019-10-18 10:00:00
 2                  gender    (null)      2019-10-18 10:00:00
 1                  gender    F           2019-10-18 10:00:00
 1                  gender    M           2019-10-18 10:00:00

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Вопрос заключается в следующем: как БД должно знать, что тип 1 - это человек, и вы ожидаете от него пола и возраста, а тип 2 - это кошка, и вы ожидаете, что цвет хвоста?

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

select type, name, (select color from <the other table> where <the attributes match>),
from first table where <conditions>

Но я боюсь, что это в значительной степени ваш единственный вариант

0 голосов
/ 21 октября 2019

Наконец, я прекратил использовать два SQL-запроса. Первый извлекает список возможных атрибутов из атрибутов

SELECT key FROM attributes GROUP BY key

Результаты:

age
gender

Затем я могу динамически создать второй запрос. Если в будущем будет добавлено больше атрибутов, этот запрос увеличится в размере:

SELECT SUM(count_value), a0.value, a1.value FROM counting cet 
    LEFT JOIN attributes a0 ON cnt.rowid = a0.row_id_counting AND a0.key = 'age' 
    LEFT JOIN attributes a1 ON cnt.rowid = a1.row_id_counting AND a1.key = 'gender' 
    WHERE datetime(created_at,'localtime') BETWEEN '2019-10-17 23:00:00.000000' AND '2019-10-18 23:00:00.000000’ AND cnt.type = 1 
    GROUP BY c0.value, c1.value

Результаты:

 SUM(count_value)   key       value       timestr
 1                  (null)    (null)      2019-10-18 10:00:00
 1                  age       20          2019-10-18 10:00:00
 1                  age       50          2019-10-18 10:00:00
 1                  gender    F           2019-10-18 10:00:00
 1                  gender    M           2019-10-18 10:00:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...