如何根据第三个表过滤左连接的结果

时间:2016-01-13 01:09:39

标签: sql database join

在此处扩展此问题:Efficient way to select records missing in another table,说我有以下3个表格(原始示例,请参阅下面的更好示例):

request: (id, name)
response: (id, request_id, provider_id, resource)
provider: (id, name)

首先,我想检索所有不存在结果的请求。这很简单,使用LEFT JOIN。我想要任何未针对给定requests执行的provider用简单的英语:我希望所有没有结果的请求或只有其他提供商的结果。

这是一个更好的例子:

customer: (id, email)
vehicle: (id, modelname)
testdrive: (id, vehicle_id REFERENCES vehicle(id), customer_id REFERENCES customer(id)

说鲍勃,爱丽丝,玛丽,弗雷德和乔访问汽车经销商。鲍勃和爱丽丝试驾凯美瑞,鲍勃和玛丽试驾雅阁,弗雷德和乔没有试驾任何东西。经销商希望制作两份清单:

  1. 谁没有试驾过凯美瑞?玛丽,弗雷德,乔
  2. 谁没有试驾雅阁?爱丽丝,弗雷德,乔
  3. 这是一个SQL小提琴演示:http://sqlfiddle.com/#!15/80d6a

    以下是建议的,但它不太正确(参见上面的SQL Fiddle链接),因为它还为我提供了DID测试驾驶OTHER车型的人:

    SELECT c.email
    FROM customer AS c
        LEFT JOIN testdrive AS t ON c.id=t.customer_id
        LEFT JOIN vehicle AS v ON t.vehicle_id=v.id AND v.modelname='Camry'
    WHERE v.id IS NULL;
    

2 个答案:

答案 0 :(得分:1)

SELECT c.email
FROM  customer AS c
WHERE NOT c.customer_ID IN (SELECT customer_id FROM testdrive WHERE vehicle_id=@Camry);

答案 1 :(得分:1)

试试这个:

SQL Fiddle

PostgreSQL 9.3架构设置

BEGIN;

-- DROP TABLE IF EXISTS customer;
-- DROP TABLE IF EXISTS vehicle;
-- DROP TABLE IF EXISTS testdrive;

CREATE TABLE customer (
    id SERIAL PRIMARY KEY,
    email TEXT
);

CREATE TABLE vehicle (
    id SERIAL PRIMARY KEY,
    modelname TEXT
);

CREATE TABLE testdrive (
    id SERIAL PRIMARY KEY,
    vehicle_id INTEGER REFERENCES vehicle(id),
    customer_id INTEGER REFERENCES customer(id)
);

INSERT INTO customer (email) VALUES
    ('Bob@foo.org'), ('Alice@bar.net'), ('Mary@baz.com'),
    ('Fred@int.edu'), ('Joe@mut.var');

INSERT INTO vehicle (modelname) VALUES ('Camry'), ('Accord');

INSERT INTO testdrive (vehicle_id, customer_id)
VALUES
    (1, 1), -- Camry, Bob
    (1, 2), -- Camry, Alice
    (2, 1), -- Accord, Bob
    (2, 3); -- Accord, Mary

-- Fred and Joe never test drove anything.
-- Mary didn't test drive the Camry.
-- Alice didn't test drive the Accord.

-- How do I query to find the list of customers who didn't test
-- drive anything, for each vehicle model?

-- Customers who didn't test drive the Camry:
-- Mary, Fred, Joe
SELECT c.email
FROM customer AS c
    LEFT JOIN testdrive AS t ON c.id=t.customer_id
    LEFT JOIN vehicle AS v ON t.vehicle_id=v.id AND v.modelname='Camry'
WHERE v.id IS NULL;

-- Customers who didn't test drive the Accord:
-- Alice, Fred, Joe

COMMIT;

查询1

SELECT *
FROM customer c
WHERE NOT EXISTS 
( SELECT * 
  FROM testdrive t 
  INNER JOIN vehicle v 
     on v.id = t.vehicle_id
  WHERE v.modelname = 'Camry' AND t.customer_id = c.id)

<强> Results

| id |        email |
|----|--------------|
|  3 | Mary@baz.com |
|  4 | Fred@int.edu |
|  5 |  Joe@mut.var |

查询2

SELECT *
FROM customer c
WHERE NOT EXISTS 
( SELECT * 
  FROM testdrive t 
  INNER JOIN vehicle v 
     on v.id = t.vehicle_id
  WHERE v.modelname = 'Accord' AND t.customer_id = c.id)

<强> Results

| id |         email |
|----|---------------|
|  2 | Alice@bar.net |
|  4 |  Fred@int.edu |
|  5 |   Joe@mut.var |