Laravel Eloquent donde el campo es X o nulo

3 minutos de lectura

Tengo una tabla como esta:

table
- field1: tinyint
- field2: varchar (nullable)
- datefield: timestamp (nullable)

Ahora quiero obtener todas las entradas donde field1 es 1, field2 es nulo y donde datefield es más pequeño que X o nulo. Ya probé algo como esto:

$query = Model::where('field1', 1)
            ->whereNull('field2')
            ->where('datefield', '<', $date)
            ->orWhereNull('datefield');

pero eso no funciona. Siempre recibo todas las entradas donde el campo de fecha es nulo. No importa cuáles sean los otros campos. También traté de dividirlo en 2 consultas: primero obtenga cada fila donde el campo de fecha sea más pequeño que X o nulo y luego (según esto) obtenga cada campo donde el campo 1 sea 1 y el campo 2 sea nulo.

El resultado fue el mismo. ¿Alguna idea de cómo hacer esto?

avatar de usuario
Jaime

Parece que necesitas hacer uso de cláusulas where avanzadas.

Dada esa búsqueda en field1 y field2 es constante los dejaremos como están, pero vamos a ajustar su búsqueda en datefield un poquito.

Prueba esto:

$query = Model::where('field1', 1)
    ->whereNull('field2')
    ->where(function ($query) {
        $query->where('datefield', '<', $date)
            ->orWhereNull('datefield');
    }
);

Si alguna vez necesita depurar una consulta y ver por qué no funciona, puede ser útil ver qué SQL está ejecutando en realidad. puedes encadenar ->toSql() hasta el final de su consulta elocuente para generar el SQL.

  • ¡Esto me ahorró algo de frustración! Gracias.

    – Bhargav Nanekalva

    14/03/2017 a las 19:00

  • se puede hacer con algo como: whereIn(‘column’,[‘value’,null]) ?

    – Shafi

    28 de febrero de 2018 a las 9:34

  • @MASh no estoy seguro. Escribí esto hace bastante tiempo y fue el mejor enfoque en ese momento. ¿Por qué no darle una oportunidad?

    – Jaime

    28 de febrero de 2018 a las 9:40

  • Uso el enfoque que escribiste aquí normalmente. Intenté y no obtuvo nada de la base de datos. Es posible que los motores de base de datos traten el nulo de forma diferente al valor. Quería saber si hay forma de pasar el nulo dentro de la matriz.

    – Shafi

    28 de febrero de 2018 a las 10:06

  • @MASh: Sí, las bases de datos tratan los valores y NULL de manera diferente (la cadena “null” es un valor normal). Las condiciones normales en las que compara valores tienen un resultado definido. Las comparaciones en NULL no están definidas porque NULL representa algo desconocido y comparar un valor con algo desconocido no puede conducir a un resultado. Para verificar si algo es NULL dentro de una consulta, use “IS” -> “where field1 IS NULL”

    – frío

    24 de marzo de 2018 a las 15:47


Podría fusionar dos consultas juntas:

$merged = $query_one->merge($query_two);

Usar coalesce() convierte nulo a 0:

$query = Model::where('field1', 1)
    ->whereNull('field2')
    ->where(DB::raw('COALESCE(datefield_at,0)'), '<', $date)
;

Si está confundido acerca de dónde colocar get()/first() para obtener la colección o una sola fila, esta es la forma:

$query = Model::where('field1', 1)
    ->whereNull('field2')
    ->where(function ($query) {
        $query->where('datefield', '<', $date)
            ->orWhereNull('datefield');
    }
)->get();

¿Ha sido útil esta solución?