在具有联接和多表/字段ORDER BY的查询中,如何设置LIMIT偏移量以从唯一ID字段标识的特定行开始?

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

假设我有四个表:tbl1 ... tbl4。每个字段都有一个唯一的数字id字段。 tbl1tbl2tbl3每个都具有序列中下一个表的外键字段。例如。 tbl1具有tbl2_id外键字段,依此类推。每个表还具有一个字段order(以及与该问题无关的其他字段)。

直接连接所有四个表以返回tbl1的所有行以及其他三个字段中的相应字段。通过ORDER BY字段的特定order组合对结果集进行排序也很容易。仅返回与id中某些特定tbl1相对应的行也很容易,例如WHERE tbl1.id = 7777

问题:哪种查询最有效地返回(例如)从id=7777对应的行开始的100行,order字段的特定组合确定的顺序

使用ROW_NUMBER或(在MySQL版本<8中对其进行仿真)来获取id = 7777行的位置,然后在同一查询的新版本中使用该位置来设置LIMIT中的偏移量条款将是一种方法。 (之间有读取锁定。)但是可以在单个查询中完成吗?

# FIRST QUERY: get row number of result row where tbl1.id = 7777

SELECT x.row_number 
FROM 
   (SELECT @row_number:=@row_number+1 AS row_number, tbl1.id AS id
    FROM (SELECT @row_number:=0) AS t, tbl1
    INNER JOIN tbl2 ON tbl2.id = tbl1.tbl2_id
    INNER JOIN tbl3 ON tbl3.id = tbl2.tbl3_id
    INNER JOIN tbl4 ON tbl4.id = tbl3.tbl4_id
    WHERE <some conditions>
    ORDER BY tbl4.order, tbl3.order, tbl2.order, tbl1.order
   ) AS x 
WHERE id=7777;

存储以上查询中的行号,并用它来绑定以下查询中的:offset

# SECOND QUERY : Get 100 rows starting from the one with id=7777

SELECT x.field1, x.field2, <etc.> 
FROM 
  (SELECT @row_number:=@row_number+1 AS row_number, field1, field2
   FROM (SELECT @row_number:=0) AS t, tbl1
   INNER JOIN tbl2 ON tbl2.id = tbl1.tbl2_id
   INNER JOIN tbl3 ON tbl3.id = tbl2.tbl3_id
   INNER JOIN tbl4 ON tbl4.id = tbl3.tbl4_id
   WHERE <same conditions as before>
   ORDER BY tbl4.order, tbl3.order, tbl2.order, tbl1.order
  ) AS x 
LIMIT :offset, 100;
mysql subquery limit offset row-number
1个回答
0
投票

澄清问题

在一般情况下,您不会要求输入WHERE id1 > 7777。相反,您有一个(11,22,33,44)元组,并且您想“从上次中断的地方继续”。

两次讨论,并

这很混乱,但并非不可能。参见Iterating through a compound key。 Ig给出了一个使用2列进行操作的示例;来自4个表的4列是此类的扩展。

一个变体

这里是这样的另一讨论:https://dba.stackexchange.com/questions/164428/should-i-store-data-pre-ordered-rather-than-ordering-on-the-fly/164755#164755

[实际上实现这种方法时,我发现让“ 100”(LIMIT)灵活些可以更容易地思考。这个想法是:向前前进100行(使用LIMIT 100,1)。假设您得到(111,222,333,444)。如果您当前位于(111,...),则处理id2 / 3/4。如果是(113,...),则执行WHERE id1 < 113并保留id2 / 3/4的任何规范。这意味着要获取少于100行,但它使您不愿开始id1 = 113。

即,它涉及构造具有1到4个条件的WHERE子句。

在所有情况下,您的查询都显示为ORDER BY id1, id2, id3, id4LIMIT的唯一用途是在探针中以找出第100行(带有LIMIT 100,1)多远。

我想我可以为此挖出一些旧的Perl代码。

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