MySQL使用多个列/键连接3个表

MySQL使用多个列/键连接3个表,mysql,sql,join,key,multiple-tables,Mysql,Sql,Join,Key,Multiple Tables,完全新手到mySQL。因此,任何帮助都将不胜感激 我有3张表--购物车,用户,操作 carts: +------------+-------------+-------+ | cartId | session_id | userId| +------------+-------------+-------+ users: +----------+-------------+ | usedId | email | +----------+-------------+

完全新手到mySQL。因此,任何帮助都将不胜感激

我有3张表--
购物车
用户
操作

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

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

actions:
+-------------+------------------+---- ---------+
| session_id  | impressionAction | impressionId | 
+-------------+------------------+-----+--------+
carts
中,每行有一个
session\u id

users
中,每行有一个
userId

actions
中,每个
session\u id
都有多行,计算该会话的所有操作

我想
JOIN
这三个表的输出类似于

+------+-------------+--------+------------------+--------------+-------+
userId | session_id  | cartId | impressionAction | impressionId | email |
+------+-------------+--------+------------------+--------------+-------+
其中每个
userId
session_id
将有多行;基本上是一个扁平的文件。我想如果我们在
userId
上加入
carts
users
导致说
A
,然后在
session\u id`上加入
A
actions',我们就到家了

样本预期输出为:

+------------+-------------+--------+------------------+--------------+---------+
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|
+------------+-------------+--------+------------------+--------------+---------+** 
我不知道如何在没有一个公用键的情况下连接3个表。我甚至不知道它叫什么类型的连接


从本质上讲,我们试图用非重叠键连接3个表,通过第一个
join
收集一个公共键,然后用第三个键连接中间键。这称为交叉连接吗?如果没有,有名字吗?

请原谅我的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

这只会将所有内容合并在一起,如果您有多对一的关系,您将拥有重复的购物车记录

用户可以选择许多产品,将其添加到购物车中;单人间 用户可能有多个购物车,在活动结束时,他们可以 通过电子邮件将购物车发送给他们自己;用户的操作存储在 操作表

这就是我对结构的看法(记住您的数据)

正如您在下面看到的,我首先加入carts,然后加入actions,因为只有表carts同时包含用户和会话数据

carts和actions上会话id旁边的
[FK]*
可能看起来是外键,但在本例中不是-,因为没有单独的会话表将其作为PK(主键)放置

您询问了
join
-它与
内部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  |
+---------+------------+---------+---------------+-------------+-----------------+
+---------+------------+------------+------------+-------------+-----------------+
| card_id | user_id    | product_id | session_id | action_name | impression_id   |
+---------+------------+------------+------------+-------------+-----------------+
| 1       | 1          | 5          | 1aaaa      | ADD         | 1               |
| 6       | 1          | 6          | 1cccc      | ADD         | 8               |
+---------+------------+------------+------------+-------------+-----------------+
注意
:无法保证会话的唯一性

(更新)工作


UPDATE:(查找和删除重复项)

我已经更新了,以模拟重复记录(当用户在同一会话中添加相同的产品时)。使用下面的语句,您将能够检索那些重复的行

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
结果:

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

更好的是,您可以检查用户是否已经添加了所选产品,并且不要再添加两次。

这可能会变得很糟糕。你在做一个基于树的连接<代码>A->B
A->C
。您将得到未定义的结果,特别是在B和C对A中的任何“父”记录有不同数量的匹配记录的情况下。看起来carts:users关系是1:1,但如果是1:n/n:1,则所有赌注都无效。一个用户可以有多个carts?@Relevant:yes,s/he可以,哪个会产生不同的
会话\u id
您能提供一个预期输出的示例吗?@eager\u learner313检查这个如果这是您想要的,我将粘贴该语句作为答案:)不同DBMS之间有许多共同点。MySql中允许查询中的所有关键字。@相关:如何取出重复项并使输出与我发布的类似?示例输出中有重复项。我所说的重复是指多次列出cartid0001。那么这个解决方案能满足您的需要吗?就连接机制而言,很快就会发生以下情况吗
carts
users
结合形成,比如说,
carts\u users
表,然后与
动作
结合形成最终的表
carts\u users\u动作
?此外,表格的顺序是否重要?我是否可以这样做:
从carts作为c.user\u id=u.user\u id作为u在c.user\u id=u.user\u id作为a在a.session\u id=c.session\u id按u.user\u id、c.cart\u id排序?也就是说,将
carts
作为第一个表?@eager\u learner313一般来说,
join
顺序并不重要,但如果您使用
内部join
;尽管如此,至少对我来说,这不是一个正确的观点,因为用户是启动操作的人,而不是购物车本身:)当使用
join
时,老实说,我在考虑这个问题,不知何故,我不喜欢在非主键/外键上连接表。(c.本案中的会话a.会话);此外,无法保证会话的唯一性(如果使用on