wheredate query left inner laravel laravel-4

laravel - left - Unir con condición adicional utilizando Query Builder o Eloquent



query builder laravel (6)

Intento agregar una condición en la consulta de unión utilizando el generador de consultas de Laravel.

Esta es la consulta que estoy tratando de reescribir con QB:

$results = DB::select('' SELECT DISTINCT * FROM rooms LEFT JOIN bookings ON rooms.id = bookings.room_type_id AND ( bookings.arrival between ? and ? OR bookings.departure between ? and ? ) WHERE bookings.room_type_id IS NULL LIMIT 20'', array(''2012-05-01'', ''2012-05-10'', ''2012-05-01'', ''2012-05-10'') );

Sé que puedo usar Raw Ex [ressions ( http://four.laravel.com/docs/queries#raw-expressions ), pero luego habrá puntos de inyección SQL. He intentado lo siguiente (con el generador de consultas), pero la consulta generada (y obviamente, los resultados de la consulta) no son lo que pretendía:

$results = DB::table(''rooms'') ->distinct() ->leftJoin(''bookings'', function($join) { $join->on(''rooms.id'', ''='', ''bookings.room_type_id''); }) ->whereBetween(''arrival'', array(''2012-05-01'', ''2012-05-10'')) ->whereBetween(''departure'', array(''2012-05-01'', ''2012-05-10'')) ->where(''bookings.room_type_id'', ''='', NULL) ->get();

Esta es la consulta generada por Laravel:

select distinct * from `room_type_info` left join `bookings` on `room_type_info`.`id` = `bookings`.`room_type_id` where `arrival` between ? and ? and `departure` between ? and ? and `bookings`.`room_type_id` is null

Como puede ver, la consulta generada no tiene la estructura (especialmente en el alcance de JOIN. ¿Es posible agregar condiciones adicionales al unirse en QB?).

¿Cómo puedo construir la misma consulta usando el Query Builder de Laravel (si es posible)? ¿Es mejor usar Eloquent, o debería quedarse con DB :: select?


Estoy usando laravel5.2 y podemos agregar combinaciones con diferentes opciones, puede modificar según su requisito.

Option 1: DB::table(''users'') ->join(''contacts'', function ($join) { $join->on(''users.id'', ''='', ''contacts.user_id'')->orOn(...);//you add more joins here })// and you add more joins here ->get(); Option 2: $users = DB::table(''users'') ->join(''contacts'', ''users.id'', ''='', ''contacts.user_id'') ->join(''orders'', ''users.id'', ''='', ''orders.user_id'')// you may add more joins ->select(''users.*'', ''contacts.phone'', ''orders.price'') ->get(); option 3: $users = DB::table(''users'') ->leftJoin(''posts'', ''users.id'', ''='', ''posts.user_id'') ->leftJoin(''...'', ''...'', ''...'', ''...'')// you may add more joins ->get();


Hay una diferencia entre las consultas crudas y las selecciones estándar (entre los métodos DB::raw y DB::select ).

Puede hacer lo que quiera usando un DB::select y simplemente colocar en el ? marcador de posición como lo hace con las declaraciones preparadas (en realidad es lo que está haciendo).

Un pequeño ejemplo:

$results = DB::select(''SELECT * FROM user WHERE username=?'', [''jason'']);

El segundo parámetro es una matriz de valores que se utilizará para reemplazar los marcadores de posición en la consulta de izquierda a derecha.


Puede replicar los paréntesis en la combinación izquierda:

LEFT JOIN bookings ON rooms.id = bookings.room_type_id AND ( bookings.arrival between ? and ? OR bookings.departure between ? and ? )

es

->leftJoin(''bookings'', function($join){ $join->on(''rooms.id'', ''='', ''bookings.room_type_id''); $join->on(DB::raw(''( bookings.arrival between ? and ? OR bookings.departure between ? and ? )''), DB::raw(''''), DB::raw('''')); })

Luego tendrá que establecer los enlaces más tarde usando "setBindings" como se describe en esta publicación de SO: ¿Cómo enlazar parámetros a una consulta de DB sin procesar en Laravel que se usa en un modelo?

No es bonito, pero funciona.


Si tiene algunos params, puede hacer esto.

$results = DB::table(''rooms'') ->distinct() ->leftJoin(''bookings'', function($join) use ($param1, $param2) { $join->on(''rooms.id'', ''='', ''bookings.room_type_id''); $join->on(''arrival'',''='',DB::raw("''".$param1."''")); $join->on(''arrival'',''='',DB::raw("''".$param2."''")); }) ->where(''bookings.room_type_id'', ''='', NULL) ->get();

y luego devuelve tu consulta

devolver $ resultados;


El ejemplo de consulta SQL como este

LEFT JOIN bookings ON rooms.id = bookings.room_type_id AND (bookings.arrival = ? OR bookings.departure = ?)

Laravel se une con múltiples condiciones

->leftJoin(''bookings'', function($join) use ($param1, $param2) { $join->on(''rooms.id'', ''='', ''bookings.room_type_id''); $join->on(function($query) use ($param1, $param2) { $query->on(''bookings.arrival'', ''='', $param1); $query->orOn(''departure'', ''='',$param2); }); })


$results = DB::table(''rooms'') ->distinct() ->leftJoin(''bookings'', function($join) { $join->on(''rooms.id'', ''='', ''bookings.room_type_id''); $join->on(''arrival'',''>='',DB::raw("''2012-05-01''")); $join->on(''arrival'',''<='',DB::raw("''2012-05-10''")); $join->on(''departure'',''>='',DB::raw("''2012-05-01''")); $join->on(''departure'',''<='',DB::raw("''2012-05-10''")); }) ->where(''bookings.room_type_id'', ''='', NULL) ->get();

No estoy seguro si la cláusula between se puede agregar a la unión en laravel.

Notas:

  • DB :: raw () ordena a Laravel que no devuelva las comillas.
  • Al pasar un cierre para unir métodos puede agregar más condiciones de unión, on () agregará AND condition y orOn () agregará O condición.