我有一个查询,它连接自身以获取每个唯一列表的最新或最旧的订单记录。
SELECT
lists.ordered,
cnt1.*
FROM
cnt_lists as cnt1
LEFT JOIN
lists
on
cnt1.list_id = lists.id
LEFT JOIN
cnt_lists as cnt2
on
(cnt1.list_id = cnt2.list_id AND cnt1.id < cnt2.id)
WHERE
cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296') and cnt1.listable_type = 'Movie';
这个查询效果很好,但是lists.ordered
可以是 0 或 1。当 lists.ordered = 0
时我想要 on
中的运算符声明为cnt1.id < cnt2.id
但是当 lists.ordered = 1
我希望将其逆转cnt1.id > cnt2.id
.
有没有办法根据 CASE
动态定义运算符陈述?下面的内容不起作用,但我正在考虑想法。
SELECT
lists.ordered,
CASE
WHEN lists.ordered = 1 THEN '>'
ELSE '<'
END AS operator,
cnt1.*
FROM
cnt_lists as cnt1
LEFT JOIN
lists
on
cnt1.list_id = lists.id
LEFT JOIN
cnt_lists as cnt2
on
(cnt1.list_id = cnt2.list_id AND cnt1.id operator cnt2.id)
WHERE
cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296') and cnt1.listable_type = 'App\\Models\\Movie';
是否有一种方法可以提取每个列表的最高顺序和最低顺序,并且我可以确定在 PHP 端使用这两条记录中的哪一条?
我只是在寻找想法,因为我试图避免必须单独查询每个列表的 N + 1 查询问题。
最佳答案
依赖动态查询是很困惑的。您最好将该运算符拉入 WHERE
查询的一部分并将其与 OR 配对:
SELECT
lists.ordered,
cnt1.*
FROM
cnt_lists as cnt1
LEFT JOIN
lists
on
cnt1.list_id = lists.id
LEFT JOIN
cnt_lists as cnt2
on
(cnt1.list_id = cnt2.list_id)
WHERE
cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296')
and cnt1.listable_type = 'Movie'
AND (
cnt2.id IS NULL /* Including this here because you have a LEFT JOIN */
(lists.ordered = 1 AND cnt1.id < cnt2.id) OR
(lists.ordered = 0 AND cnt1.id > cnt2.id)
);
您的另一个选择是直接将该逻辑放入连接逻辑中。这可能更容易阅读。
SELECT
lists.ordered,
cnt1.*
FROM
cnt_lists as cnt1
LEFT JOIN
lists
on
cnt1.list_id = lists.id
LEFT JOIN
cnt_lists as cnt2
on
(cnt1.list_id = cnt2.list_id AND (
(lists.ordered = 1 AND cnt1.id < cnt2.id) OR
(lists.ordered = 0 AND cnt1.id > cnt2.id)
))
WHERE
cnt2.id is null and cnt1.list_id in ('3176', '3295', '3296')
and cnt1.listable_type = 'Movie'
;
您可以选择包含 <
在您的最终输出中,但这不会特别有用。
如果您*真的*想要创建动态查询,则很难一步完成,but it is definitely doable .
关于php - MySQL中有没有办法根据CASE动态定义运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40933600/