2

我有两个表,tbl_footbl_bar,我想tbl_foo.foo_id = tbl_bar.foo_id在 on-clause 中加入这些表。但是,对于每个都tbl_bar.baz_id应该有一行tbl_foo.foo_id(即使不tbl_bar存在这样的条目)。我该如何编写这样的查询?

下面有关于架构和我想要的结果的更多信息。

  • 编辑:每一行必须有一个foo_idand baz_id
  • 编辑2:在下面添加tbl_baz

期望的结果

+--------+--------+--------+------------+
| bar_id | baz_id | foo_id | some_field |
+--------+--------+--------+------------+
|      1 |    101 |      1 | foo        |
|      2 |    101 |      2 | bar        |
|      3 |    101 |      3 | baz        |
|   NULL |    101 |      4 | bin        |
|      4 |    102 |      1 | foo        |
|   NULL |    102 |      2 | bar        |
|      5 |    102 |      3 | baz        |
|   NULL |    102 |      4 | bin        |
+--------+--------+--------+------------+

表:tbl_foo

+--------+------------+
| foo_id | some_field |
+--------+------------+
|      1 | foo        |
|      2 | bar        |
|      3 | baz        |
|      4 | bin        |
+--------+------------+

表:tbl_bar

+--------+--------+--------+
| bar_id | baz_id | foo_id |
+--------+--------+--------+
|      1 |    101 |      1 |
|      2 |    101 |      2 |
|      3 |    101 |      3 |
|      4 |    102 |      1 |
|      5 |    102 |      3 |
+--------+--------+--------+

表:tbl_baz

+--------+
| baz_id |
+--------+
|    101 |
|    102 |
+--------+

SQL 架构

CREATE TABLE tbl_foo (
    foo_id INT,
    some_field VARCHAR(255),
    PRIMARY KEY (foo_id)
);

INSERT INTO tbl_foo VALUES
(1, 'foo'),
(2, 'bar'),
(3, 'baz'),
(4, 'bin');

CREATE TABLE tbl_bar (
    bar_id INT,
    baz_id INT,
    foo_id INT,
    PRIMARY KEY (bar_id, baz_id),
    FOREIGN KEY (baz_id) REFERENCES tbl_baz (baz_id),
    FOREIGN KEY (foo_id) REFERENCES tbl_foo (foo_id)
);

INSERT INTO tbl_bar VALUES
(1, 101, 1),
(2, 101, 2),
(3, 101, 3),
(4, 102, 1),
(5, 102, 3);

CREATE TABLE tbl_baz (
    baz_id INT,
    PRIMARY KEY (baz_id)
);

INSERT INTO tbl_baz VALUES
(101),
(102);
4

3 回答 3

3

就像 mwigdalh 说的那样,没有办法用给定的表来实现那个输出。如果有另一张 baz 表,那就有办法了。问题是下面突出显示的记录基本上是凭空捏造的,毫无意义。你可以很容易地把“meh”放在每一个中,输出也会很有意义。

+--------+--------+--------+------------+
| bar_id | baz_id | foo_id | some_field |
+--------+--------+--------+------------+
|      1 |    101 |      1 | foo        |
|      2 |    101 |      2 | bar        |
|      3 |    101 |      3 | baz        |
|   NULL |   *101*|      4 | bin        |
|      4 |    102 |      1 | foo        |
|   NULL |   *102*|      2 | bar        |
|      5 |    102 |      3 | baz        |
|   NULL |   *102*|      4 | bin        |
+--------+--------+--------+------------+

如果您在更接近真实世界的示例中提供一些上下文,则可能会发现完全不同的输出可以达到您想要的结果。

于 2012-04-04T13:30:42.530 回答
1

可能正在寻找这样的查询:

更新

基于新的 tbl_baz:

select y.bar_id, x.baz_id, x.foo_id, x.some_field
from (
    select a.foo_id, a.some_field, b.baz_id
    -- Cross foo_id with all baz_id
    from tbl_foo as a, tbl_baz as b
) as x
    -- Get the bar_id where it exists for each foo_id/baz_id combo
    left join tbl_bar as y on x.foo_id = y.foo_id
        and x.baz_id = y.baz_id
order by x.baz_id, x.foo_id

这是基于您希望查看每个 baz_id 的每个 foo_id 的假设,而不管多对多表中有什么。

为什么您可能不想要这个,或者可能想要更新您的多对多表的示例:

如果我们用“person”和“car”替换“foo”和“baz”,这个查询本质上是说每个人都拥有每辆车。可能是这种情况,但肯定不会在“所有权”多对多表(条形图)中表示。

于 2012-04-04T13:53:29.747 回答
0

模糊,你不能从这里到达那里。您正在要求一个结果,该结果指定一个baz_idfor 行,其中没有相应的行 from tbl_bar。在这种情况下,根本没有办法构造缺失的数据。

您的架构不正确,或者您需要一些自定义默认逻辑来处理在tbl_bar.

于 2012-04-04T13:26:45.197 回答