用户可以创建“标签”。可以将标签分配给多个父母。我们正在尝试做的是找出标签组合的使用频率。我们还想知道这些组合链接到哪些父母。
我们认为如果标签具有相同的标签,则可以一起使用
Parent a, value $200
Child Tag x
Child Tag y
Child Tag z
Parent b, value $300
Child Tag x
Child Tag z
Parent c, $400
Child Tag y
Child Tag z
在上述情况下,标签y,z一起使用了2次-在父级a和父级c上。 y,z组合的总价值为600美元。
同样,标签x,z在父级a和父级b上一起使用。 x,z组合的总价值为$ 500。
我们要执行的搜索类型是:
"find combinations of any 2 tags that share a parent"
"find the total value for each combination of 2 tags that share a parent"
我很困惑如何在查询中执行此操作,并且我继续使用临时表。
答案 0 :(得分:0)
首先,必须认识到这是一个多对多问题,而不是一对多问题。每个父母都有很多标签,并且每个标签都适用于许多父母。
如果您修改模型以反映此情况,则将有一个类似以下的表格:
parent_id | tag_id
------------------
a | x
a | y
a | z
b | x
b | z
c | y
c | z
等等。
现在,您可以将表自身连接起来,以获得每个父级的标签组合列表:
select p1.parent_id, p1.tag_id, p2.tag_id from parent_has_tag as p1 left join parent_has_tag as p2 using(parent_id) where p2.tag_id > p1.tag_id;
>
用于消除成对报告“ x,x”,并且同时返回“ x,y”和“ y,x”。
这并不是您真正想要的,但这是使您能够回答上述问题的基石。例如,“每个标签组合出现多少次?”回答如下:
SELECT count(1) AS `frequency`, GROUP_CONCAT(p1.parent_id) AS `parents`, CONCAT_WS(',', p1.tag_id, p2.tag_id) AS `pair`
FROM parent_has_tag AS p1 LEFT JOIN parent_has_tag AS p2 USING(parent_id) where p2.tag_id > p1.tag_id
GROUP BY `pair`;
这会给您每个标签组合出现多少次,以及包含这些组合的父级的免费列表。但是,您下一个问题的答案只是加总父母的价值观:
SELECT count(1) AS `frequency`,
SUM(`parents`.`value`) AS `total_value`,
GROUP_CONCAT(p1.parent_id) AS `parents`,
p1.tag_id AS `tag1`,
p2.tag_id AS `tag2`
FROM parent_has_tag AS p1
JOIN parent_has_tag AS p2 ON p1.parent_id = p2.parent_id AND p2.tag_id > p1.tag_id
JOIN parents on p1.parent_id = parents.id
GROUP BY p1.tag_id, p2.tag_id
我认为还有优化的空间(例如,此版本比上面的版本更聪明),但这是获取所需数据的核心。
使用上述起始数据,该查询的结果如下:
+-----------+-------------+---------+------+------+
| frequency | total_value | parents | tag1 | tag2 |
+-----------+-------------+---------+------+------+
| 2 | 600 | c,a | x | y |
| 2 | 500 | b,a | x | z |
| 1 | 200 | a | y | z |
+-----------+-------------+---------+------+------+