我们说我有下表:
id | name | parent_id
-- | ------ | ---------
1 | monkey | NULL
2 | nut | NULL
3 | mies | NULL
4 | monkey | 1
5 | nut | 1
现在,我想要使用唯一name
获取所有记录,最好使用parent_id = 1
,否则使用parent_id IS NULL
。因此查询的结果将返回记录[3, 4, 5]
。
如何用Eloquent实现这一目标?
我已尝试将groupBy( 'name' )
与orderBy( 'entity_id', 'desc' )
结合使用,但groupBy
似乎在orderBy
之前执行,因此如果我在asc
之间切换,结果始终相同{1}}和desc
条款中的orderBy
。
我也试过玩distinct()
而没有任何运气。
更新
当然,我可以执行两个查询并合并结果,但我想知道是否可以使用单个查询完成此操作。
更新2
目前,我在Eloquent的unique()
课程中使用Collection
方法解决了这个问题:
$parent = Parent::find( 1 );
$items = $parent->items()
->orWhereNull( 'parent_id' )
->orderBy( 'parent_id', 'desc' )
->get()
->unique( 'name' );
答案 0 :(得分:1)
方法#1:
在GROUP BY
name
上使用aggregate
等MAX
功能时,您需要先parent_id
max_parent_id
。因此,您的偏好是保留的。
稍后在加入NULL
时,您需要检查NULL
。因为IS NULL
只能使用IS NOT NULL
中的MySQL
或max_parent_id
进行比较。如果name
的{{1}}为NULL
,那么您应该在最终结果集中允许它(请参阅本案例中如何使用IF
)
SELECT
YT.*
FROM your_table YT
INNER JOIN
(
SELECT
name,
MAX(parent_id) AS max_parent_id
FROM your_table
--WHERE parent_id IS NULL OR parent_id IN (1)
GROUP BY name
) AS t
ON YT.name = t.name AND
IF(t.max_parent_id IS NULL, TRUE, YT.parent_id = t.max_parent_id);
方法#2:
使用MySQL user-defined variables
您也可以实现这一目标。
方法#2 比例
SELECT
t.id,
t.name,
t.parent_id
FROM
(
SELECT
IF(@prev_name = name, @rn := @rn + 1,
IF(@prev_name := name, @rn := 1, @rn := 1)
) AS rank,
your_table.*
FROM your_table
CROSS JOIN
(
SELECT @rn := 0, @prev_name := NULL
) AS var
ORDER BY name, parent_id DESC
) AS t
WHERE t.rank = 1
ORDER BY t.id;