如何从多个表中获取唯一行,这些表彼此具有外键但都具有单独表的键

问题描述 投票:0回答:1

4张桌子-第一,第二,第三,第四。

FIRST {
firstId
otherColumns
}

SECOND {
secondId
firstId
thirdId
otherColumns
}

THIRD {
thirdId
firstId
fourthId
otherColumns
}

FOURTH {
fourthId
firstId
secondId
thirdId
}

Firsts pk 是 FirstId

Second、third 和 fourth 在 FirstId 上都有 fks。如果我在 FirstId 上加入所有 4 个表,我会得到第二个第三个和第四个的所有组合。

相反,我想要每个行中的所有不同行。另一种表达方式是,如果我从第二个第三个和第四个位置选择 FirstId=={{someFirstId}}。

所以如果我在第二行有 2 行,在第三行有 2 行,在第四行有 3 行,我想取回 7 行。相反,如果我加入这四个表,我会取回所有可能的行组合。

我怎样才能在一次查询中得到 7?我已经尝试过 Distinct 但这似乎并没有改变它,并且不确定我如何才能获得子查询来做到这一点

我也试过用三个子查询做一个等价的操作,但这又让我得到了返回的行数,作为每个子查询中所有行的乘积而不是总和

编辑:得到具体的

SELECT "second", "third", "fourth" 
FROM 
Join second on "second."firstId" = "first.firstId" 
Join third on "third."firstId" = "first.firstId"
Join fourth on "fourth."firstId" = "first.firstId" 
where firstId=x

得到所有连接的乘积,总共 12 行。我想从每个行中返回单独的行,总结

postgresql
1个回答
0
投票

请使用实际的表定义和示例数据而不是文本描述来更新问题。没有足够的细节来提供具体的答案;但是,我将尝试解决抽象问题。在加入结果之前,必须为每个子表计算聚合(总和)。

为了演示实现此结果的方法,我将仅使用两个子表,但可以根据需要扩展该模式。设置如下:

DROP TABLE IF EXISTS third_table;

DROP TABLE IF EXISTS second_table;

DROP TABLE IF EXISTS first_table;

CREATE TABLE first_table (
    first_id serial PRIMARY KEY,
    label text
);

CREATE TABLE second_table (
    second_id serial PRIMARY KEY,
    first_id integer REFERENCES first_table (first_id),
    value1 integer,
    value2 integer
);

CREATE TABLE third_table (
    third_id serial PRIMARY KEY,
    first_id integer REFERENCES first_table (first_id),
    value1 integer,
    value2 integer
);

INSERT INTO first_table (label) (
        VALUES ('group1'), ('group2'));

INSERT INTO second_table (first_id, value1, value2) (
        VALUES (1, 1211, 1221), (1, 1, 1), (2, 2213, 2221), (2, NULL, 2), (2, NULL, NULL));

INSERT INTO third_table (first_id, value1, value2) (
        VALUES (1, 1311, 1321), (1, 1, 1), (1, 1, 1), (2, 2313, 2321), (2, NULL, 2), (2, NULL, NULL));

根据你的问题,我推测期望的结果应该是:

 first_id | second_value1_sums | second_value2_sum | third_value1_sum | third_value2_sum 
----------+--------------------+-------------------+------------------+------------------
        1 |               1212 |              1222 |             1313 |             1323
        2 |               2213 |              2223 |             2313 |             2323
(2 rows)

(second_table 和 third_table 中的值使得总和为四位编码。)

这是产生这些结果的查询:

SELECT
    first_table.first_id,
    second_sums.value1 AS second_value1_sums,
    second_sums.value2 AS second_value2_sum,
    third_sums.value1 AS third_value1_sum,
    third_sums.value2 AS third_value2_sum
FROM
    first_table
    JOIN (
        SELECT
            second_table.first_id,
            sum(second_table.value1) AS value1,
            sum(second_table.value2) AS value2
        FROM
            second_table
        GROUP BY
            second_table.first_id) second_sums USING (first_id)
JOIN (
    SELECT
        third_table.first_id,
        sum(third_table.value1) AS value1,
        sum(third_table.value2) AS value2
    FROM
        third_table
    GROUP BY
        third_table.first_id) third_sums USING (first_id)
ORDER BY
    first_table.first_id;

还有其他构造查询的方法。每个子查询都可以表示为公用表表达式 (CTE)。 CTE 可以更具可读性;但是,它们也会损害性能,因为它们会产生优化障碍。

LATERAL
也可以使用连接,但如果从父表请求大量行,则性能可能会明显降低,因为每个父行都需要一个额外的查询。

© www.soinside.com 2019 - 2024. All rights reserved.