Laravel雄辩,当行符合2个条件时,如何从查询中排除行?

问题描述 投票:4回答:1

所以我试图创建一个Laravel雄辩的查询。它有点复杂,并且有一堆子句,一切运行良好,并且查询单个表。但是,我想添加一个特定的条件,如下所述。

->where('date', '>', Carbon::now())

这个条件工作正常,但我希望这个条件只适用于特定的行!假设我想要上面适用的where子句的条件是:

->where('row_type', '=', 'someType')

现在我不想过滤row_type ='someType'的所有行,也不想过滤date> Carbon :: now()的所有行。

我只想过滤日期> Carbon :: now()WHEN row_type ='someType'的行。

当然,'date'和'row_type'都是我表中的列。

现在为了简化逻辑,我想要做的基本上是EXCLUDE行,其中两个(date <Carbon :: now()AND row_type ='someType')都为真。

这是不是可以在eloquent中进行单个查询而不插入原始sql?

我能够在原始sql中重现我的查询:

select id, date, row_type from my_table where case when row_type = 'someType' then date > '2019-03-01%' end;
php laravel eloquent
1个回答
1
投票

现在为了简化逻辑,我想要做的基本上是EXCLUDE行,其中两个(date <Carbon :: now()AND row_type ='someType')都为真。

要么应用正式的布尔逻辑!(A and B) = !A or !B,要么只注意“排除两者都是真的”等同于“包括任何一个是假的”。因此,我们包括那些日期未过去(即未来)或类型不是someType的行。

->where('row_type', '!=', 'someType')->orWhere('date', '>', Carbon::now())

如果你还有其他条件,包括orWhere会搞砸那些,你应该只使用这个嵌套:

// ...other wheres...
->where(function($query) {
    $query->where('date', '>', Carbon::now())->orWhere('row_type', '!=', 'someType');
})
->where( // ...other wheres...

我将尝试通过SQL来表明这是有效的。

CREATE TABLE my_table(Id integer PRIMARY KEY, row_type text, date date);

/* First row is someType and past - it should be excluded */
INSERT INTO my_table VALUES(1,'someType', '2019-03-01');
INSERT INTO my_table VALUES(2,'someType', '2019-03-31');
INSERT INTO my_table VALUES(3,'otherType', '2019-03-01');
INSERT INTO my_table VALUES(4,'otherType', '2019-03-01');
COMMIT;

op中的查询是这样的:

SELECT 'Cases from the OP' as '';
SELECT id, row_type, date 
FROM my_table
WHERE
  CASE
    WHEN row_type = 'someType'
      THEN date > '2019-03-22%'
  END;

/* returns */
2|someType|2019-03-31

它甚至没有用你的语言表达。它还排除了row_type不是someType的每一行。这相当于row_type = 'someType' AND date > '2019-03-22'。为了排除你所说的应该排除的内容,你必须使它更复杂:

SELECT id, row_type, date 
FROM my_table
WHERE
  CASE
    WHEN row_type = 'someType'
      THEN date > '2019-03-22'
    ELSE 1
  END;

/* returns */
2|someType|2019-03-31
3|otherType|2019-03-01
4|otherType|2019-03-01

但是这样写它会更简单,更合适(在实际存在多个案例的情况下是合适的):

SELECT ' ' as '';
SELECT 'The same using OR' as '';
SELECT id, row_type, date
FROM my_table
WHERE
  (row_type != 'someType' OR date > '2019-03-22');

/* returns */
2|someType|2019-03-31
3|otherType|2019-03-01
4|otherType|2019-03-01

我把你的条件包括在括号中,因为你说你想要添加其他语句。这就是where(function($q) {$q->...})会做的事情。

© www.soinside.com 2019 - 2024. All rights reserved.