完全外部联接不会返回右表的结果

时间:2019-09-04 13:42:20

标签: sql postgresql

我的应用程序包含可以预订的用户列表。我们需要为这些预订支付用户费用。我需要获取需要付款的用户列表。如果用户有预订,或者使用创建的没有预订的付款,可以向用户付款。

我尝试了以下方法:

SELECT 
  users.id as user_id,
  user_bookings.id as user_booking_id,
  user_bookings.payment_id as user_booking_payment_id,
  payments.id as payment_id
FROM 
  users 
  LEFT OUTER JOIN user_bookings ON user_bookings.user_id = user.id 
  FULL JOIN payments ON payments.id = user_bookings.payment_id

Where payments.issued = false;

但是它没有列出没有预订的付款用户。它仅列出创建了预订的用户。如何获得没有预订的付款用户?

编辑

我尝试了以下查询:

具有37271的用户具有以下付款记录:

 select payments.id, payments.issued from payments where payments.user_id=37271;

   id   | issued 
--------+--------
 133046 | f
 133045 | t
(2 rows)

以下是我的预订:

select user_bookings.id, user_bookings.payment_issued, user_bookings.payment_id from user_bookings where user_id=37271;

   id   | payment_issued    | payment_id 
--------+-------------------+---------------
 541136 | t                 |        133045
 541137 | t                 |        133045
(2 rows)

在运行以下查询时:

SELECT u.id as user_id, ub.id as user_booking_id, ub.payment_id as user_booking_payment_id,
       p.id as payment_id, p.issued as payments_issued
FROM users u LEFT OUTER JOIN
     user_bookings ub
     ON ub.user_id = u.id FULL JOIN
     (SELECT p.*
      FROM payments p
      WHERE NOT p.issued
     ) p
     ON p.id = ub.payment_id

where users.id=37271;

它不返回没有预订的付款,但返回已付款:

 user_id | user_booking_id | user_booking_payment_id | payment_id | payments_issued 
---------+-----------------+-------------------------+------------+-----------------
   37271 |          541137 |                  133045 |            | 
   37271 |          541136 |                  133045 |            | 
(2 rows)

2 个答案:

答案 0 :(得分:2)

SELECT 
  users.id as user_id,
  user_bookings.id as user_booking_id,
  user_bookings.payment_id as user_booking_payment_id,
  payments.id as payment_id,
FROM 
  users 
  LEFT OUTER JOIN user_bookings ON user_bookings.user_id = user.id 
  FULL JOIN payments ON payments.id = linguist_bookings.payment_id

Where payments.issued = false
   OR payments.issued IS NULL;

如果使用外部联接,则在WHERE子句中将其转换为内部联接;因为NULL = [something]永远不是真的。

答案 1 :(得分:0)

您正在将外部join变成inner join。用full outer join处理过滤非常棘手。我推荐一个子查询:

SELECT u.id as user_id, ub.id as user_booking_id, ub.payment_id as user_booking_payment_id
       p.id as payment_id,
FROM users u LEFT OUTER JOIN
     user_bookings ub
     ON ub.user_id = u.id FULL JOIN
     (SELECT p.*
      FROM payments p
      WHERE NOT p.issued
     ) p
     payments p
     ON p.id = ub.payment_id;

但是,我想问你为什么要在这里FULL JOIN。您可以从其他表格中获取没有其他信息的付款ID。

我希望LEFT JOIN就足够了:

SELECT u.id as user_id, ub.id as user_booking_id, ub.payment_id as user_booking_payment_id,
       p.id as payment_id
FROM users u LEFT JOIN
     user_bookings ub
     ON ub.user_id = u.id LEFT JOIN
     payments p
     ON p.id = ub.payment_id AND NOT p.issued;