postgresql 无法为三个表编写查询

x8goxv8g  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(2)|浏览(131)

我需要写下面的查询。假设我们有一个这样的表结构:
main_table

id PRIMARY KEY
column1,
column2,
column3

table_1

id PRIMARY KEY
main_table_id REFERENCES main_table NOT NULL,
column1,
column2,
column3

table_2

id PRIMARY KEY
table_1_id REFERENCES table1 NOT NULL,
necessary_column

我需要通过到table_1的链接从main_table中获取在table_2.necessary_column中具有给定值的数据。我该怎么做?
我写了一个查询2表,但我不知道如何做到这一点与3表。

wr98u20j

wr98u20j1#

通过到table_1的链接从table_2中获取main_table中具有necessary_column列的数据
有很多种方法。使用EXISTS演示一个查询,以便从main_table中获取唯一行:

SELECT *
FROM   main_table m
WHERE EXISTS (
   SELECT  -- can be empty
   FROM   table_1 t1
   JOIN   table_2 t2 ON t2.table_1_id = t1.id
   WHERE  t1.main_table_id = m.id
   AND    t2.necessary_column = $input
   );

你也可以只连接所有三个表,但这可能会增加行,你可能不得不添加另一个昂贵的DISTINCT

SELECT m.* -- or: DISTINCT m.*
FROM   main_table m
JOIN   table_1 t1 ON t1.main_table_id = m.id
JOIN   table_2 t2 ON t2.table_1_id = t1.id
WHERE  t2.necessary_column = $input;
uujelgoq

uujelgoq2#

问题描述不是很清楚。所以,很难肯定地回答。但是,似乎你需要更好地理解内连接和左连接之间的区别,以及我们可以链接这些操作。
让我们尝试使用一些更清晰的结构如下:

创建这些表并填充一些数据

-- create
CREATE TABLE USER (
  user_id INTEGER PRIMARY KEY,
  user_name TEXT NOT NULL
);

CREATE TABLE DOG (
  dog_id INTEGER PRIMARY KEY,
  dog_name TEXT NOT NULL,
  ower_id INTEGER,
  FOREIGN KEY (ower_id) REFERENCES USER(user_id)
);

CREATE TABLE TOY (
  toy_id INTEGER PRIMARY KEY,
  dog_id INTEGER,
  toy_name TEXT NOT NULL,
  FOREIGN KEY (dog_id) REFERENCES DOG(dog_id)
);

-- insert
INSERT INTO USER VALUES (1001, 'Anna'); -- Anna has 2 dogs
INSERT INTO USER VALUES (1002, 'Bob');  -- Bob has 1 dog
INSERT INTO USER VALUES (1003, 'Carl'); -- Carl does not have dogs

INSERT INTO DOG VALUES (2001, 'Snoopy'   , 1001); -- Snoopy belongs to Anna and have 2 toys
INSERT INTO DOG VALUES (2002, 'Fluffy'   , 1001); -- Fluffy belongs to Anna and have 1 toy
INSERT INTO DOG VALUES (2003, 'Snow Ball', 1002); -- Snow Ball belongs to Bob and have no toys
INSERT INTO DOG VALUES (2004, 'Zorro',     NULL); -- Zorro has one toy but no owner

INSERT INTO TOY VALUES (3001, 2001, 'Bone');  -- Bone belongs to Snoopy
INSERT INTO TOY VALUES (3002, 2001, 'Stick'); -- Stick belongs to Snoopy
INSERT INTO TOY VALUES (3003, 2002, 'Ball');  -- Ball belongs to Fluffy
INSERT INTO TOY VALUES (3004, 2004, 'Mask');  -- Mask belongs to Zorro

查询

如果您想链接这三个需要所有连接的表之间的关系,您可以在任何方向上这样做。
换句话说,这个查询的结果:

SELECT 
  user_name,
  dog_name,
  toy_name
FROM TOY -- go to all toys
INNER JOIN DOG ON DOG.dog_id = toy.dog_id -- then search for the dogs owners of the toys (required)
INNER JOIN USER ON user.user_id = dog.ower_id; -- then search for the users owners of the dogs

-- |-----------|----------|----------|
-- | user_name | dog_name | toy_name |
-- |-----------|----------|----------|
-- | Anna      | Snoopy   | Bone     |
-- | Anna      | Snoopy   | Stick    |
-- | Anna      | Fluffy   | Ball     |
-- |-----------|----------|----------|

这一个的结果是一样的:

SELECT
  user_name,
  dog_name,
  toy_name
FROM USER -- go to all users
INNER JOIN DOG ON dog.ower_id = user.user_id -- then go to the users dogs (required)
INNER JOIN TOY ON toy.dog_id = dog.dog_id; -- then go to the dogs toys (required)

-- |-----------|----------|----------|
-- | user_name | dog_name | toy_name |
-- |-----------|----------|----------|
-- | Anna      | Snoopy   | Bone     |
-- | Anna      | Snoopy   | Stick    |
-- | Anna      | Fluffy   | Ball     |
-- |-----------|----------|----------|

但是,当我们使用 left join 链接查询时,链的顺序会有所不同。在下面的查询中可以看到:

SELECT 
  user_name,
  dog_name,
  toy_name
FROM TOY -- go to all toys
LEFT JOIN DOG ON DOG.dog_id = toy.dog_id -- then search for the dogs owners of the toys (optional)
LEFT JOIN USER ON user.user_id = dog.ower_id; -- then search for the users owners of the dogs (optional)

-- |-----------|----------|----------|
-- | user_name | dog_name | toy_name |
-- |-----------|----------|----------|
-- | Anna      | Snoopy   | Bone     |
-- | Anna      | Snoopy   | Stick    |
-- | Anna      | Fluffy   | Ball     |
-- | NULL      | Zorro    | Mask     | -- Notice that Zorro has no owner
-- |-----------|----------|----------|

SELECT
  user_name,
  dog_name,
  toy_name
FROM USER -- go to all users
LEFT JOIN DOG ON dog.ower_id = user.user_id -- then go to the users dogs (optional)
LEFT JOIN TOY ON toy.dog_id = dog.dog_id; -- then go to the dogs toys (optional)

-- |-----------|-----------|----------|
-- | user_name | dog_name  | toy_name |
-- |-----------|-----------|----------|
-- | Anna      | Snoopy    | Bone     |
-- | Anna      | Snoopy    | Stick    |
-- | Anna      | Fluffy    | Ball     |
-- | Bob       | Snow Ball | NULL     | -- Notice that Snow Ball have no toys
-- | Carl      | NULL      | NULL     | -- Notice that Carl have no dogs
-- |-----------|-----------|----------|

相关问题