当前位置: 首页 > 面试题库 >

聚合多个联接表上的函数

汪典
2023-03-14
问题内容

我有三个表:

CREATE TABLE foo (
    id bigint PRIMARY KEY,
    name text NOT NULL
);

CREATE TABLE foo_bar (
    id bigint PRIMARY KEY,
    foo_id bigint NOT NULL
);

CREATE TABLE tag (
    name text NOT NULL,
    target_id bigint NOT NULL,
    PRIMARY KEY (name, target_id)
);

我正在尝试创建一个视图,以便获得table的所有字段,where中foo的项目计数以及foo_barwherefoo.id = foo_bar.foo_id中所有标签的文本数组foo.id = tag.target_id。如果我们有:

INSERT INTO foo VALUES (1, 'one');
INSERT INTO foo VALUES (2, 'two');
INSERT INTO foo_bar VALUES (1, 1);
INSERT INTO foo_bar VALUES (2, 1);
INSERT INTO foo_bar VALUES (3, 2);
INSERT INTO foo_bar VALUES (4, 1);
INSERT INTO foo_bar VALUES (5, 2);
INSERT INTO tag VALUES ('a', 1);
INSERT INTO tag VALUES ('b', 1);
INSERT INTO tag VALUES ('c', 2);

结果应返回:

foo.id    | foo.name     | count       | array_agg
--------------------------------------------------
1         | one          | 3           | {a, b}
2 聽 聽 聽 聽 | two 聽 聽 聽 聽 聽| 2 聽 聽 聽 聽 聽 | {c}

这是我到目前为止所拥有的:

SELECT DISTINCT f.id, f.name, COUNT(b.id), array_agg(t.name)
FROM foo AS f, foo_bar AS b, tag AS t
WHERE f.id = t.target_id AND f.id = b.foo_id
GROUP BY f.id, b.id;

这些是我得到的结果(请注意,这count是不正确的):

foo.id    | foo.name     | count       | array_agg
--------------------------------------------------
1         | one          | 2           | {a, b}
2 聽 聽 聽 聽 | two 聽 聽 聽 聽 聽| 1 聽 聽 聽 聽 聽 | {c}

count始终是标签的数量,而不是不同的计foo_bar数值。我尝试重新排序/修改GROUP BYSELECT子句,它们返回不同的结果,但不是我想要的结果。我认为我在使用该array_agg()功能时遇到了麻烦,但是我不确定是否是这种情况或如何解决。


问题答案:
SELECT f.id, f.name, b.fb_ct, t.tag_names
FROM   foo f
LEFT JOIN  (
    SELECT foo_id AS id, count(*) AS fb_ct
    FROM   foo_bar
    GROUP  BY 1
    ) b USING (id)
LEFT JOIN  (
    SELECT target_id AS id, array_agg(name) AS tag_names
    FROM   tag
    GROUP  BY 1
    ) t USING (id)
ORDER  BY f.id;

产生所需的结果。

  • 用显式JOIN语法重写。使其更易于阅读和理解(和调试)。

  • 通过联接到多个1:n相关的表,行将相互乘以产生笛卡尔乘积-这是非常昂贵的废话。这是CROSS JOIN代理人意料之外的。有关的:

    • 两个SQL LEFT JOINS产生不正确的结果
    • 为避免这种情况,请在汇总()之前将 一个 n-table与1-table最多连接GROUP BY。您可以聚合两次,但是 在将 它们n联接到-table 之前 ,分别聚合-tables更加干净快捷1
  • 与您的原始图片(带有隐式INNER JOIN)相反。我通常 LEFT JOIN 会避免丢失或中foo没有匹配行的行。foo_bar``tag

  • 一旦将意外CROSS JOIN内容从查询中删除,则无需再添加DISTINCT任何内容-假设这foo.id是唯一的。



 类似资料:
  • 问题内容: 我在#temp表中具有以下数据: 我想做以下操作,即 一行将在两列上加法,即 另一行将在三列上减法加法,即 我曾尝试在SQL Server中使用case语句。 以下是所需的输出 哪里& 我曾尝试使用SQL SERVER Case语句,但未获得正确的输出 问题答案: 我看到至少有两种方法可以得到这些结果。分组或枢纽 在下面的示例中,显示了2种方法。 请注意,使用的是SUM(VALUE)而

  • 问题内容: 假设我有两个现有表,“ dogs”和“ cats”: 如何使用此输出编写查询? 问题答案:

  • 问题内容: 嗨,这是我的情况,我有那些桌子 所以我想总计费用和税款,然后按客户ID分组,这是我的查询 因此,如果我有1个客户费用,而我使用SUM函数时却有2个税额,那么它会计算两次费用,例如,如果要向我显示10 $,则向我显示20 $ 我知道如何通过子查询解决此问题,但是我想知道是否有任何选项可以获取没有子查询之类的正确值,例如我在上面可以使用的修改内容以解决该问题。 谢谢 ! 没有子查询的更新答

  • 问题内容: 我如何将下面的MySQL查询写入Rails ActiveRecord 我知道如何在两个表上编写联接;但是,我对如何在3个表上使用联接不是很有信心。 问题答案: 要重写您在问题中遇到的SQL查询,我认为它应该类似于以下内容(尽管我很难完全可视化您的模型关系,所以这有点猜测): …这样该方法可以同时处理两个联接以及子句,最后是调用。 作为更多参考: 如果要将多个关联加入同一模型,则可以简单

  • 我是(My)SQL的新手,需要一些帮助:在数据库中,我有3个表,一个例子: 购买: 制造者: 型号: 在表purchases中,model是一个外键,它链接到model.id。在模型中,“制造商”是一个外键,它与“制造商id”相链接。 我的目标是一个如下图所示的表格: 我知道如何在表购买中加入以获取型号的名称。不幸的是,我不知道如何获取制造商? 我的SQL-查询:

  • 问题内容: 大多数SQL方言都接受以下两个查询: 现在显然当您需要外部联接时,需要第二种语法。但是,在进行内部联接时,为什么我应该更喜欢第二种语法(反之亦然)? 问题答案: 在大多数现代数据库中,不赞成使用仅列出表并使用子句指定连接条件的旧语法。 这不仅是为了展示,当您在同一查询中同时使用INNER和OUTER联接时,旧语法可能会变得模棱两可。 让我给你举个例子。 假设您的系统中有3个表: 每个表