2015-04-09 2 views
1
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) 

В RailsLEFT JOIN не возвращает все строки из другой таблицы

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 строк. Пожалуйста, помогите мне в этом.

+0

изменить 'paybacks.success = true' на' paybacks.success = true или окупаемость.успех равен нулю –

+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) 

Если вы не сделаете это, все записи в bookings Wich имеют никаких записей в paybacks не будут игнорироваться.

Вход:

бронирования:

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 

И если у вас есть success = true в вашем белый Если вы проигнорируете вторую строку, потому что

success is null 
+0

@TarunGarg См. мой обновленный ответ. Надеюсь это поможет. – Jens

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, как нуль

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 | 
+------+------+--------+------+ 

Теперь, если мы добавим, где условие будет фильтровать данные после соединения, как

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 | 
+------+------+--------+------+ 

Теперь, если мы хотим, чтобы данные левой таблицы, которые будут отображаться, то нам нужно переместить где состояние в присоединяющемся состояние, в результате, не совпадающие записи будут отображаться как нулевые.

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 | 
+------+------+--------+------+ 

Так что в вашем случае вы должны переместить где условие в присоединяющемся условие, если вы хотите, чтобы все записи из левой таблицы, чтобы быть там в результате.

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