eag*_*313 2 mysql sql join key multiple-tables
mySQL 完全新手。因此,任何帮助将不胜感激。
我有3 张桌子- carts, users, actions。
carts:
+------------+-------------+-------+
| cartId | session_id | userId|
+------------+-------------+-------+
users:
+----------+-------------+
| usedId | email |
+----------+-------------+
actions:
+-------------+------------------+---- ---------+
| session_id | impressionAction | impressionId |
+-------------+------------------+-----+--------+
Run Code Online (Sandbox Code Playgroud)
在 中carts,每行有一个session_id。
在 中users,每行有一个userId。
在 中,每个会话的所有操作actions都有多个行。session_id
我希望JOIN这三个表的输出类似于
+------+-------------+--------+------------------+--------------+-------+
userId | session_id | cartId | impressionAction | impressionId | email |
+------+-------------+--------+------------------+--------------+-------+
Run Code Online (Sandbox Code Playgroud)
每个userId和有多行session_id;本质上是一个扁平化的文件。我想如果我们JOIN carts得到say然后和session_id`,我们就到家了。usersuserIdAJOIN Aactions' on
预期输出示例为:
+------------+-------------+--------+------------------+--------------+---------+
userId | session_id | cartId | impressionAction | impressionId | email |
+------------+-------------+--------+------------------+--------------+---------+
| 1234 | abc3f45 | 0001 | LOGIN | 2032 |ab@yc.com|
| 1234 | abc3f45 | 0001 | ADD | 4372 |ab@yc.com|
| 1234 | abc3f45 | 0001 | ADD | 4372 |ab@yc.com|
| 1234 | abc3f45 | 0001 | SENDMAIL | ab@yc.com |ab@yw.com|
| 4567 | def4rg4 | 0002 | LOGIN | 2032 |db@yw.com|
| 4567 | def4rg4 | 0002 | ADD | 4372 |db@yw.com|
| 4567 | def4rg4 | 0002 | REMOVE | 3210 |db@yw.com|
+------------+-------------+--------+------------------+--------------+---------+**
Run Code Online (Sandbox Code Playgroud)
我不知道如何在没有一个公共键的情况下 JOIN 3 个表。我什至不知道它被称为什么类型的连接。
本质上,我们试图连接 3 个具有不重叠键的表,通过第一个表收集一个公共键JOIN,然后将中间值与第三个表连接起来。这也叫a CROSS JOIN? 如果没有的话有名字吗?
摘自您上面的评论
用户可以选择许多产品,将它们添加到购物车;单个用户可以拥有多个购物车,并且在活动结束时,他们可以通过电子邮件将购物车发送给自己;用户的操作存储在操作表中
这就是我如何看待结构(考虑到你的数据)
+---------------------+ +---------------------+ +---------------------+
| users | | carts | | actions |
+---------------------+ +---------------------+ +---------------------+
| user_id [PK] |--| | cart_id [PK] | | impression_id [PK] |
| email | |--| user_id [FK] | | action_name |
| | | product_id [FK] | |--| session_id [FK]* |
+---------------------+ | session_id [FK]* |--| | |
| | +---------------------+
+---------------------+
Run Code Online (Sandbox Code Playgroud)
正如您在上面看到的,我首先加入购物车,然后加入操作,因为只有表购物车同时具有用户和会话数据。
购物车和操作上的 session_id旁边[FK]*的内容可能看起来是外键,但在本例中它不是 - 因为没有单独的会话表可以将其作为 PK(主键)放置
你问的是join- 它与 相同inner join。INNER JOIN 通过根据连接谓词组合两个表(A 和 B)的列值来创建新的结果表。该查询将 A 的每一行与 B 的每一行进行比较,以查找满足连接谓词的所有行对。
这是表格的可能内容
+------------------------+
| users |
+------------------------+
| id | email |
+------+-----------------+
| 1 | first@mail.org |
| 2 | second@mail.org |
| 3 | third@mail.org |
+------+-----------------+
+------------------------------------------+
| carts |
+------------------------------------------+
| id | user_id | product_id | session_id |
+------+---------+------------+------------+
| 1 | 1 | 5 | 1aaaa |
| 2 | 2 | 5 | 2ffff |
| 3 | 3 | 8 | 3ddddd |
| 4 | 1 | 5 | 1aaaaa |
| 5 | 3 | 9 | 3bbbbb |
| 6 | 1 | 6 | 1ccccc |
+------+---------+------------+------------+
+-------------------------------+
| actions |
+-------------------------------+
| id | name | session_id |
+------+-----------+------------+
| 1 | ADD | 1aaaa |
| 2 | ADD | 2ffff |
| 3 | SENDMAIL | 3ddddd |
| 4 | ADD | 3ddddd |
| 5 | SENDMAIL | 2ffff |
| 6 | ADD | 1aaaaa |
| 7 | REMOVE | 3ddddd |
| 8 | ADD | 1ccccc |
| 9 | ADD | 3bbbbb |
| 10 | SENDMAIL | 3bbbbb |
+------+-----------+------------+
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,表购物车中有六种产品,add表操作中有六个操作。此外,您可以看到 id=1 的用户购买了三个产品,但不是同时购买,因为有两个会话;id=3 的用户也在不同时间购买了这两种产品等等......
SQL语句
SELECT u.user_id, c.session_id, c.cart_id, a.impression_id, a.action_name, u.email
FROM users AS u
INNER JOIN carts AS c ON c.user_id = u.user_id
INNER JOIN actions AS a ON a.session_id = c.session_id
ORDER BY u.user_id, c.session_id, c.cart_id
Run Code Online (Sandbox Code Playgroud)
结果:
+---------+------------+---------+---------------+-------------+-----------------+
| user_id | session_id | cart_id | impression_id | action_name | email |
+---------+------------+---------+---------------+-------------+-----------------+
| 1 | 1aaaa | 1 | 1 | ADD | first@mail.org |
| 1 | 1aaaa | 1 | 6 | ADD | first@mail.org |
| 1 | 1aaaa | 4 | 1 | ADD | first@mail.org |
| 1 | 1aaaa | 4 | 6 | ADD | first@mail.org |
| 1 | 1cccc | 6 | 8 | ADD | first@mail.org |
| 2 | 2ffff | 2 | 5 | SENDMAIL | second@mail.org |
| 2 | 2ffff | 2 | 2 | ADD | second@mail.org |
| 3 | 3bbbb | 5 | 9 | ADD | third@mail.org |
| 3 | 3bbbb | 5 | 10 | SENDMAIL | third@mail.org |
| 3 | 3dddd | 3 | 3 | SENDMAIL | third@mail.org |
| 3 | 3dddd | 3 | 4 | ADD | third@mail.org |
| 3 | 3dddd | 3 | 7 | REMOVE | third@mail.org |
+---------+------------+---------+---------------+-------------+-----------------+
Run Code Online (Sandbox Code Playgroud)
Note:无法保证会话的唯一性。
(更新)工作SQL Fiddle
UPDATE: (Finding and deleting duplicates)
我更新了SQL Fiddle以模拟重复记录(当用户在同一会话中添加相同产品时)。使用以下语句,您将能够检索那些重复的行。
SELECT c.card_id, c.user_id, c.product_id, c.session_id, a.action_name, a.impression_id
FROM cards As c
INNER JOIN actions AS a ON a.session_id = c.session_id
GROUP BY c.user_id, c.product_id, c.session_id, a.action_name
HAVING count(*) > 1
Run Code Online (Sandbox Code Playgroud)
结果:
+---------+------------+------------+------------+-------------+-----------------+
| card_id | user_id | product_id | session_id | action_name | impression_id |
+---------+------------+------------+------------+-------------+-----------------+
| 1 | 1 | 5 | 1aaaa | ADD | 1 |
| 6 | 1 | 6 | 1cccc | ADD | 8 |
+---------+------------+------------+------------+-------------+-----------------+
Run Code Online (Sandbox Code Playgroud)
在上述语句的 SELECT 部分中,您可以省略除 card_id 和impression_id 之外的所有内容。在一条语句中删除这两个重复项有点棘手,因为您无法修改同一查询中子查询中选择的同一表。在这种情况下,我会避免棘手的部分(涉及另一个内部子查询),并使用单独的语句删除重复项,如下所示
-- delete duplicates from cards
--
DELETE FROM WHERE card_id IN (1,6)
-- delete duplicates from actions
--
DELETE FROM WHERE card_id IN (1,8)
Run Code Online (Sandbox Code Playgroud)
更好的是,您可以检查用户是否已添加所选产品,并且不要添加两次。