MySQL使用多个列/键加入3个表

时间:2014-07-08 18:48:19

标签: mysql sql join key multiple-tables

完成mySQL的新手。所以任何帮助将不胜感激。

我有 3个表格 - cartsusersactions

carts:
+------------+-------------+-------+
| cartId     | session_id  | userId| 
+------------+-------------+-------+

users:
+----------+-------------+
| usedId   | email       |
+----------+-------------+

actions:
+-------------+------------------+---- ---------+
| session_id  | impressionAction | impressionId | 
+-------------+------------------+-----+--------+

carts中,每行有一个session_id

users中,每行有一个userId

actions中,每个session_id有多行代表该会话的所有操作。

我想JOIN三个表使输出类似于

+------+-------------+--------+------------------+--------------+-------+
userId | session_id  | cartId | impressionAction | impressionId | email |
+------+-------------+--------+------------------+--------------+-------+

userIdsession_id会有多行;本质上是一个扁平的文件。我想如果我们JOINcarts usersuserId导致说A然后JOIN A和{{1} } session_id`,我们在家。

样本预期输出是:

actions' on

我不知道如何在没有一个公共密钥的情况下加入3个表。我甚至不知道它被称为什么类型的联接。

基本上,我们尝试使用非重叠键加入3个表,通过第一个+------------+-------------+--------+------------------+--------------+---------+ 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| +------------+-------------+--------+------------------+--------------+---------+** 收集一个公共密钥,然后将第三个加入中间密钥。这被称为JOIN吗?如果不是,有名字吗?

2 个答案:

答案 0 :(得分:3)

取自您上面的评论

  

用户可以选择多种产品,将其添加到CART中;单身   USER可能有多个CARTS,在活动结束时,他们可以   给自己发送电子邮件;用户的行动存储在   动作表

这就是我看到你的结构(记住你的数据)的方式

+---------------------+     +---------------------+     +---------------------+
| 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]* |--|  |                     |
                            |                     |     +---------------------+
                            +---------------------+    

正如您在下面所见,我首先加入购物车,然后加入行动,因为只有表格推车同时具有用户和会话数据。

购物车和操作上的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     |
+------+-----------+------------+

正如您所看到的,表格操作中有六种产品,表格操作中只有六种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

结果:

+---------+------------+---------+---------------+-------------+-----------------+
| 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  |
+---------+------------+---------+---------------+-------------+-----------------+

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

结果:

+---------+------------+------------+------------+-------------+-----------------+
| card_id | user_id    | product_id | session_id | action_name | impression_id   |
+---------+------------+------------+------------+-------------+-----------------+
| 1       | 1          | 5          | 1aaaa      | ADD         | 1               |
| 6       | 1          | 6          | 1cccc      | ADD         | 8               |
+---------+------------+------------+------------+-------------+-----------------+

在上述声明的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)

更好的是,您可以检查用户是否已添加所选产品,并且不会将其添加两次。

答案 1 :(得分:1)

请原谅我的MySql语法,因为我不知道:-p但这就是这个想法

SELECT u.userId, a.session_id, c.cartId, a.impressionAction, a.impressionId, u.email
FROM Carts c 
JOIN Users u on u.userId = c.UserId
JOIN Actions a on a.session_id = c.session_id

这只是将所有内容合并在一起,如果您有多对一的关系

,您将拥有重复的购物车记录