【问题标题】:How to select next and previous rows altogether from an ordered set of rows?如何从一组有序的行中完全选择下一行和上一行?
【发布时间】:2021-01-13 08:00:00
【问题描述】:

我根据这样的数量对前 3 个订单进行切片:

Order::orderByDesc('amount')->take(3)->get();

但现在,我必须走得更远。 orders 表有一个 created_by 列,该列与 creator (belongsTo) 关系相关联。首先,我必须根据数量对订单进行排序,然后我必须分取 5 个订单,其中给定的 created_by 值位于中间(5 条记录中的第三个)。要将其转化为业务逻辑:

在排行榜上显示特定用户的位置以及在他们前面的另外两个成员和在他们后面的另外两个成员。

考虑到我们要获取其数据的 Carol,可视化表示可能如下所示:

  • 1|姓名:爱丽丝 |订单金额:500 美元
  • 2|姓名:鲍勃 |订单金额:$400
  • 3|姓名:卡罗尔 |订单金额:$300 // 登录用户
  • 4|姓名:戴安娜 |订单金额:$200
  • 5|姓名:艾玛 |订单金额:$100

我能想到的一种方法是将所有排序的订单提取到一个集合中,然后查找下两行和前两行,但是对于大型数据集,它会消耗大量内存。如何以雄辩/以数据库为中心的方式实现这一点,而不是获取所有这些然后应用集合操作?

【问题讨论】:

  • 您可以进行 3 个查询。一个用于获取登录用户数据,一个用于上一个用户,一个用于下一个用户。基于登录用户量的第二次和第三次查询
  • 对于高级用户:Order::orderByAsc('amount')->where('amount', '>', '$user->amount') - >take(2)->get ()....... 想出个主意。

标签: sql database laravel eloquent


【解决方案1】:

我了解 SQL,并且使用窗口函数很容易做到这一点。 如果您知道记录在“排行榜”中的位置,例如 3

SELECT
    o.name,
    o.amount
FROM (
    SELECT
        o.created_by,
        o.amount,
        ROW_NUMBER() OVER (ORDER BY o.amount DESC) AS rn
    FROM Order o
) s
JOIN Creator c on c.id = s.created_by
WHERE
    s.rn BETWEEN 3 - 2 AND 3 + 2

如果您只知道创建者的姓名:

WITH Ranked (name, amount, rn)
AS (
    SELECT
        o.name,
        o.amount,
        ROW_NUMBER() OVER (ORDER BY o.amount DESC) AS rn
    FROM Order o   
    JOIN Creator c on c.id = o.created_by
)
SELECT 
    o.name,
    o.amount
FROM Ranked r
JOIN Ranked o ON o.rn BETWEEN r.rn - 2 AND r.rn + 2
WHERE r.name = `Carol`

这不是 laravel 查询,但您应该知道如何执行原始 SQL,它可以为您提供正确的方向来编写有效的查询。

【讨论】:

  • 在这两个查询中,您都在获取所有订单。这不是性能问题吗?
猜你喜欢
  • 1970-01-01
  • 2015-03-13
  • 1970-01-01
  • 2020-02-21
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 2015-01-21
  • 1970-01-01
相关资源
最近更新 更多