所以我试图创建一个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;
现在为了简化逻辑,我想要做的基本上是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->...})
会做的事情。