在 Postgres 中连接 3 个表时,结果可以按 2 个连接表中的值排序吗?
When JOINing 3 tables in Postgres, can the results be sorted by values in the 2 joined tables?
我有一个包含三个 table 的数据库。最终我想加入三个 table 并按两个 table 共享的列对它们进行排序。
一个主项目 table 带有外键 (product_id) 到两个子 tables:
项
CREATE TABLE items (
id INT NOT NULL,
product_id varchar(40) NOT NULL,
type CHAR NOT NULL
);
然后一个table分别对应typeA和typeB。它们有不同的列,但为了本练习,我只包括它们共有的列:
CREATE TABLE products_a (
id varchar(40) NOT NULL,
name varchar(40) NOT NULL,
price INT NOT NULL
);
CREATE TABLE products_b (
id varchar(40) NOT NULL,
name varchar(40) NOT NULL,
price INT NOT NULL
);
一些示例行:
INSERT INTO items VALUES
( 1, 'abc', 'a' ),
( 2, 'def', 'b' ),
( 3, 'ghi', 'a' ),
( 4, 'jkl', 'b' );
INSERT INTO products_a VALUES
( 'abc', 'product 1', 10 ),
( 'ghi', 'product 2', 50 );
INSERT INTO products_b VALUES
( 'def', 'product 3', 20 ),
( 'jkl', 'product 4', 100 );
我有一个 JOIN 工作,但我的排序没有像我期望的那样插入行。
查询:
SELECT
items.id AS item_id,
products_a.name AS product_a_name,
products_a.price AS product_a_price,
products_b.name AS product_b_name,
products_b.price AS product_b_price
FROM items
FULL JOIN products_a ON items.product_id = products_a.id
FULL JOIN products_b ON items.product_id = products_b.id
ORDER BY 3, 5 ASC;
实际结果:
item_id
product_a_name
product_a_price
product_b_name
product_b_price
1
product 1
10
NULL
NULL
3
product 2
50
NULL
NULL
2
NULL
NULL
product 3
20
4
NULL
NULL
product 4
100
想要的结果:
item_id
product_a_name
product_a_price
product_b_name
product_b_price
1
product 1
10
NULL
NULL
2
NULL
NULL
product 3
20
3
product 2
50
NULL
NULL
4
NULL
NULL
product 4
100
我意识到这是一个奇怪的 table 设置,但这种简化方式看起来比实际情况更做作。不过,最终排序与实际用例相匹配,并且更改数据库模式不是一种选择。我觉得我在这里遗漏了一些简单的东西,只是按一列或另一列排序。感谢任何帮助。
在 ORDER BY
子句中使用 COALESCE
以始终按第一个非 NULL
价格排序:
SELECT
items.id AS item_id,
products_a.name AS product_a_name,
products_a.price AS product_a_price,
products_b.name AS product_b_name,
products_b.price AS product_b_price
FROM items
FULL JOIN products_a ON items.product_id = products_a.id
FULL JOIN products_b ON items.product_id = products_b.id
ORDER BY
COALESCE(3, 5);
我有一个包含三个 table 的数据库。最终我想加入三个 table 并按两个 table 共享的列对它们进行排序。
一个主项目 table 带有外键 (product_id) 到两个子 tables:
项
CREATE TABLE items (
id INT NOT NULL,
product_id varchar(40) NOT NULL,
type CHAR NOT NULL
);
然后一个table分别对应typeA和typeB。它们有不同的列,但为了本练习,我只包括它们共有的列:
CREATE TABLE products_a (
id varchar(40) NOT NULL,
name varchar(40) NOT NULL,
price INT NOT NULL
);
CREATE TABLE products_b (
id varchar(40) NOT NULL,
name varchar(40) NOT NULL,
price INT NOT NULL
);
一些示例行:
INSERT INTO items VALUES
( 1, 'abc', 'a' ),
( 2, 'def', 'b' ),
( 3, 'ghi', 'a' ),
( 4, 'jkl', 'b' );
INSERT INTO products_a VALUES
( 'abc', 'product 1', 10 ),
( 'ghi', 'product 2', 50 );
INSERT INTO products_b VALUES
( 'def', 'product 3', 20 ),
( 'jkl', 'product 4', 100 );
我有一个 JOIN 工作,但我的排序没有像我期望的那样插入行。
查询:
SELECT
items.id AS item_id,
products_a.name AS product_a_name,
products_a.price AS product_a_price,
products_b.name AS product_b_name,
products_b.price AS product_b_price
FROM items
FULL JOIN products_a ON items.product_id = products_a.id
FULL JOIN products_b ON items.product_id = products_b.id
ORDER BY 3, 5 ASC;
实际结果:
item_id | product_a_name | product_a_price | product_b_name | product_b_price |
---|---|---|---|---|
1 | product 1 | 10 | NULL | NULL |
3 | product 2 | 50 | NULL | NULL |
2 | NULL | NULL | product 3 | 20 |
4 | NULL | NULL | product 4 | 100 |
想要的结果:
item_id | product_a_name | product_a_price | product_b_name | product_b_price |
---|---|---|---|---|
1 | product 1 | 10 | NULL | NULL |
2 | NULL | NULL | product 3 | 20 |
3 | product 2 | 50 | NULL | NULL |
4 | NULL | NULL | product 4 | 100 |
我意识到这是一个奇怪的 table 设置,但这种简化方式看起来比实际情况更做作。不过,最终排序与实际用例相匹配,并且更改数据库模式不是一种选择。我觉得我在这里遗漏了一些简单的东西,只是按一列或另一列排序。感谢任何帮助。
在 ORDER BY
子句中使用 COALESCE
以始终按第一个非 NULL
价格排序:
SELECT
items.id AS item_id,
products_a.name AS product_a_name,
products_a.price AS product_a_price,
products_b.name AS product_b_name,
products_b.price AS product_b_price
FROM items
FULL JOIN products_a ON items.product_id = products_a.id
FULL JOIN products_b ON items.product_id = products_b.id
ORDER BY
COALESCE(3, 5);