左连接不会返回另一个表中的所有行

时间:2015-04-09 05:34:33

标签: mysql ruby-on-rails

SELECT paybacks.id as payback_id, paybacks.booking_id, bookings.status, paybacks.success, bookings.id as booking_id FROM `bookings` LEFT JOIN `paybacks` ON `paybacks`.`booking_id` = `bookings`.`id` WHERE (bookings.status = 1) AND (paybacks.success = true)

在Rails中

Booking.where("bookings.status = 1").joins("LEFT JOIN `paybacks` ON `paybacks`.`booking_id` = `bookings`.`id`").select("paybacks.points_to_redeem as payback_points_used").where("paybacks.success = true" ).select("bookings.id as booking_id")

我在预订表中有1659行,但只有800行。请帮助我。

3 个答案:

答案 0 :(得分:3)

您必须将第二个where条件添加到开启条件:

SELECT paybacks.id as payback_id, paybacks.booking_id, bookings.status, paybacks.success, bookings.id as booking_id FROM `bookings` LEFT JOIN `paybacks` ON `paybacks`.`booking_id` = `bookings`.`id` AND (paybacks.success = true)
 WHERE (bookings.status = 1) 

如果您不这样做,bookingspaybacks中没有记录的所有记录都将被忽略。

输入:

预订:

ID |  attribute1 | attribute2
1  | xxx         | yyyy
2  | yyy         | zzzz

的回报:

ID |  bookings_id | success
1  |  1           | true

离开加入后你就拥有了这个:

booking.ID | attribute1 |attribute2 | paybacks.ID | bookung_id | success
1          | xxx        | yyyy      |  1          |  1         | true
2          | yyy        | zzzz      |  null       |  null      | null

如果你在where语句中有success = true,你将忽略第二行,因为

success is null

答案 1 :(得分:2)

让我们举一个例子说明这一点。 当我们离开连接条件时,它会在连接后过滤记录。

让我们说我们有2张桌子

mysql> select * from test1;
+------+------+--------+
| id   | val  | status |
+------+------+--------+
|    1 | a    |      0 |
|    2 | b    |      1 |
|    3 | c    |      1 |
|    4 | d    |      1 |
|    5 | d    |      0 |
+------+------+--------+
5 rows in set (0.00 sec)

mysql> select * from test2 ;
+------+------+------+
| id   | t1id | val  |
+------+------+------+
|    1 |    1 | aaa  |
|    2 |    2 | aaa  |
|    3 |    3 | aaa  |
|    4 |    5 | eeee |
+------+------+------+
4 rows in set (0.00 sec)

如果我们需要从test1获取所有数据并通过执行left join到test2,它将返回test1中的所有数据和test2中的非匹配记录为null

select t1.*,
t2.t1id from 
test1 t1 left join test2 t2 on t1.id = t2.t1id ;



 +------+------+--------+------+
| id   | val  | status | t1id |
+------+------+--------+------+
|    1 | a    |      0 |    1 |
|    2 | b    |      1 |    2 |
|    3 | c    |      1 |    3 |
|    4 | d    |      1 | NULL |
|    5 | d    |      0 |    5 |
+------+------+--------+------+

现在,如果我们添加where条件,它将在连接后过滤数据

select t1.*,
t2.t1id 
from test1 t1 
left join test2 t2 on t1.id = t2.t1id  where t1.status = 1;


+------+------+--------+------+
| id   | val  | status | t1id |
+------+------+--------+------+
|    2 | b    |      1 |    2 |
|    3 | c    |      1 |    3 |
|    4 | d    |      1 | NULL |
+------+------+--------+------+

甚至

select t1.*,
 t2.t1id from test1 t1 
 left join test2 t2 on t1.id = t2.t1id  
 where t2.val = 'aaa'

+------+------+--------+------+
| id   | val  | status | t1id |
+------+------+--------+------+
|    1 | a    |      0 |    1 |
|    2 | b    |      1 |    2 |
|    3 | c    |      1 |    3 |
+------+------+--------+------+

现在,如果我们想要显示左表数据,那么我们需要将where条件移动到连接条件,结果不匹配的记录将显示为null。

select t1.*,
t2.t1id from test1 t1 
left join test2 t2 on t1.id = t2.t1id 
and t1.status = 1 and  t2.val = 'aaa'

+------+------+--------+------+
| id   | val  | status | t1id |
+------+------+--------+------+
|    1 | a    |      0 | NULL |
|    2 | b    |      1 |    2 |
|    3 | c    |      1 |    3 |
|    4 | d    |      1 | NULL |
|    5 | d    |      0 | NULL |
+------+------+--------+------+

因此,在您的情况下,如果您希望左表中的所有记录都在结果中,则必须将where条件移动到连接条件。

答案 2 :(得分:1)

我得到了答案。请检查以下查询。我在and条件下添加了join。它给了我确切的答案。

SELECT bookings.id as booking_id, paybacks.points_to_redeem as payback_points_used FROM `bookings` LEFT JOIN `paybacks` ON `paybacks`.`booking_id` = `bookings`.`id` and paybacks.success = true WHERE (bookings.status = 1) GROUP BY paybacks.booking_id
相关问题