如何进行多对多表外连接?

发布于 2024-07-10 14:51:05 字数 820 浏览 5 评论 0原文

我有 3 个表:foo、foo2bar 和 bar。 foo2bar 是 foo 和 bar 之间的多对多映射。 以下是内容。

select * from foo
+------+
| fid  |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+

select * from foo2bar
+------+------+
| fid  | bid  |
+------+------+
|    1 |    1 |
|    1 |    2 |
|    2 |    1 |
|    2 |    3 |
|    4 |    4 |
+------+------+

select * from bar
+------+-------+------+
| bid  | value | zid  |
+------+-------+------+
|    1 |     2 |   10 |
|    2 |     4 |   20 |
|    3 |     8 |   30 |
|    4 |    42 |   30 |
+------+-------+------+

我想要请求的是,“给我一个 zid 为 30 的所有 fid 和值的列表”

我希望得到所有 fid 的答案,因此结果如下所示:

+------+--------+
| fid  | value  |
+------+--------+
|    1 |   null |
|    2 |      8 |
|    3 |   null |
|    4 |     42 |
+------+--------+

I have 3 tables, foo, foo2bar, and bar. foo2bar is a many to many map between foo and bar. Here are the contents.

select * from foo
+------+
| fid  |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
+------+

select * from foo2bar
+------+------+
| fid  | bid  |
+------+------+
|    1 |    1 |
|    1 |    2 |
|    2 |    1 |
|    2 |    3 |
|    4 |    4 |
+------+------+

select * from bar
+------+-------+------+
| bid  | value | zid  |
+------+-------+------+
|    1 |     2 |   10 |
|    2 |     4 |   20 |
|    3 |     8 |   30 |
|    4 |    42 |   30 |
+------+-------+------+

What I want to request is, "Give me a list of all the fid and values with zid of 30"

I expect an answer for all the fids, so the result would look like:

+------+--------+
| fid  | value  |
+------+--------+
|    1 |   null |
|    2 |      8 |
|    3 |   null |
|    4 |     42 |
+------+--------+

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

国际总奸 2024-07-17 14:51:05
SELECT * FROM foo
  LEFT OUTER JOIN (foo2bar JOIN bar ON (foo2bar.bid = bar.bid AND zid = 30))
  USING (fid);

在 MySQL 5.0.51 上测试。

这不是子查询,它只是使用括号来指定连接的优先级。

SELECT * FROM foo
  LEFT OUTER JOIN (foo2bar JOIN bar ON (foo2bar.bid = bar.bid AND zid = 30))
  USING (fid);

Tested on MySQL 5.0.51.

This is not a subquery, it just uses parentheses to specify the precedence of joins.

望笑 2024-07-17 14:51:05
SELECT * FROM
        foo LEFT JOIN
        (
        Foo2bar JOIN bar
             ON foo2bar.bid = bar.bid AND zid = 30
        )
        ON foo.fid = foo2bar.fid;

未经测试的

SELECT * FROM
        foo LEFT JOIN
        (
        Foo2bar JOIN bar
             ON foo2bar.bid = bar.bid AND zid = 30
        )
        ON foo.fid = foo2bar.fid;

untested

半边脸i 2024-07-17 14:51:05

如果您没有返回 fid = 3 的行,那么您的服务器已损坏。

此代码应该执行我认为您想要的操作:

SELECT
    F.fid,
    SQ.value
FROM
    dbo.Foo F
LEFT OUTER JOIN
     (
     SELECT F2B.fid, B.value
     FROM dbo.Bar B
     INNER JOIN dbo.Foo2Bar F2B ON F2B.bid = B.bid WHERE B.zid = 30
     ) SQ ON SQ.fid = F.fid

请记住,如果 fid 与 zid 为 30 的两个柱相关,则可以返回 fid 的两个值。

If you're not getting back a row for fid = 3 then your server is broken.

This code should do what I think you want:

SELECT
    F.fid,
    SQ.value
FROM
    dbo.Foo F
LEFT OUTER JOIN
     (
     SELECT F2B.fid, B.value
     FROM dbo.Bar B
     INNER JOIN dbo.Foo2Bar F2B ON F2B.bid = B.bid WHERE B.zid = 30
     ) SQ ON SQ.fid = F.fid

Keep in mind that it is possible to get back two values for a fid if it is related to two bars with a zid of 30.

绿光 2024-07-17 14:51:05

弄清楚后,您就可以从您的选择开始。 不要包含您最终不想看到的列。

SELECT foo.fid, bar.value

然后我们可以做WHERE子句,可以看到正如你所表达的那样。

SELECT foo.fid, bar.value  
WHERE bar.zid = 30

现在,棘手的部分是使用 LEFT JOIN 将 FROM 子句的事物连接在一起,因为我们希望查看每个 fid,无论是否存在中间匹配:

SELECT foo.fid, bar.value  
FROM foo  
LEFT JOIN foo2bar ON foo.fid = foo2bar.fid  
LEFT JOIN bar ON foo2bar.bid = bar.bid  
WHERE bar.zid = 30
OR bar.zid IS NULL

Working it out, you can start with your select. Don't include columns you don't want to ultimately see.

SELECT foo.fid, bar.value

Then we can do the WHERE clause, which can see is just as you expressed it.

SELECT foo.fid, bar.value  
WHERE bar.zid = 30

Now the tricky part to connect things together for our FROM clause, using LEFT JOINs because we want to see every fid, whether or not there are intermediate matches:

SELECT foo.fid, bar.value  
FROM foo  
LEFT JOIN foo2bar ON foo.fid = foo2bar.fid  
LEFT JOIN bar ON foo2bar.bid = bar.bid  
WHERE bar.zid = 30
OR bar.zid IS NULL
深海蓝天 2024-07-17 14:51:05

FWIW,问题实际上并不是关于多对多:这可以很简单地作为一个联合来完成。

SQL 中真正的多对多是 CROSS JOIN

FWIW, the question isn't really about a many-to-many: this could quite simply be done as a union.

A real many-to-many in SQL is a CROSS JOIN

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文