【问题标题】:Join two tables and group properly the results加入两个表并对结果进行正确分组
【发布时间】:2020-02-15 05:13:33
【问题描述】:

我正在使用 SQL 数据库来存储一些视频分析的人数统计结果。 counting表可以总结如下:

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

后来,我想为检测到的人添加一些属性,仍然使用图像处理。 我本可以更改 counting 表,但是对于添加的每个 now 属性,我都必须手动更改 counting 表。我想要一个动态的解决方案。 创建了第二个表,名为attributes,非常简单。

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

例如,如果我的算法检测到 30 岁男性,则以下行将出现在 countingattributes 表中:

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

如果有一天我的 counting 表必须存储其他类型的数据(例如猫或车辆),我可以在 type 列下指定它,我不必存储无用的这些数据的属性,因为属性存储在另一个表中,并且是动态创建的。

我还可以在我的 SQL 请求中使用 JOIN 从 counting 中轻松检索一些具有特定属性的数据。


现在,我想每小时汇总所有具有相同属性的数据,以便从我的“计数”表中创建一些统计数据。我的第一个解决方案是:

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

即使我在年龄属性或性别属性的总和中加上 (null) (null) 行,我也只计算 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

【问题讨论】:

  • 如果您以文本形式发布示例数据或为您的预期结果提供小提琴将会很有帮助。
  • 这是实体-属性-值表设计的问题之一。当您必须回答诸如“查找所有在两个日期之间见过的性别为女性、年龄在 30 到 45 岁之间、头发颜色为棕色或棕色或黑色”...

标签: sql sqlite join


【解决方案1】:

问题是这样的:DB 怎么知道类型 1 是一个人,而你期待他们的性别和年龄,类型 2 是一只猫,你期待尾巴的颜色?

如果您知道这一点,您可以尝试构建一个将其考虑在内的查询,即。

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

但恐怕这几乎是你唯一的选择

【讨论】:

  • type 列是已知的,我忘记在我的问题中添加子句“WHERE type = 1”,感谢您指出,我编辑了我的问题。其实这个属性在这个问题上几乎没用,我只是为了解释为什么我的数据库是这样设计的。
  • 但是你的想法很好,也许我应该在attributes 表中添加一个typecolumn。然后首先是从所选类型的属性中列出我所有可能的键,并使用它来创建我的第二个请求。我试试看!
  • 或者您可以添加第三个表,该表将解释您期望每种类型的哪些属性并通过它连接 - 在这种情况下,您可以从主表内部联接到字典一,然后外部联接到附加属性,它将解决您的问题
【解决方案2】:

最后,我使用了两个 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

【讨论】:

    猜你喜欢
    • 2012-05-28
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多