Php 在MySQL分页结果中查找特定记录

Php 在MySQL分页结果中查找特定记录,php,mysql,pagination,seek,Php,Mysql,Pagination,Seek,我有一个使用LIMIT startrecord和endrecord的经典分页系统,我想知道X记录位于哪个页码 我现在唯一的想法就是递归地寻找所有的记录来找到它。但我正在寻找一种更经济的方法 有什么想法吗?您可以使用子查询创建一个包含结果及其位置的表,然后查询您正在查看的特定条目: SET @rank=0; SELECT rank, record FROM ( SELECT @rank:=@rank+1 AS rank, record FR

我有一个使用LIMIT startrecord和endrecord的经典分页系统,我想知道X记录位于哪个页码

我现在唯一的想法就是递归地寻找所有的记录来找到它。但我正在寻找一种更经济的方法


有什么想法吗?

您可以使用子查询创建一个包含结果及其位置的表,然后查询您正在查看的特定条目:

SET @rank=0; 
SELECT rank, record 
FROM (
    SELECT 
        @rank:=@rank+1 AS rank, 
        record 
    FROM table
) as subquery 
WHERE record = x;

返回的表将显示记录及其在原始查询中出现的排名。您可以将排名除以每页的结果数。。。或者将其构建到查询中。希望这能有所帮助。

请列出您要查找的记录之前的记录数。这要求您为查询假定一个自然的顺序

SELECT COUNT(id) AS c
FROM tbl
WHERE sort_field < ((SELECT sort_field FROM tbl WHERE id = 18))
OR (sort_field = ((SELECT sort_field FROM tbl WHERE id = 18)) AND id < 18);
然后只需检索c并计算ceillingc/page\u大小。这将为您的记录提供页码。要记住的唯一重要的一点是,您需要按照查询中使用limit的顺序对记录进行排序


为了描述查询的作用,它统计id为18的记录前面的记录数。唯一棘手的部分是使用与sort_字段值相同的记录,MySQL将在该字段中使用主键,在本例中使用id。这就是为什么我们的条件中有OR部分。在我的回答中,我假设您使用升序对原始查询进行排序,但如果您使用降序排序,则需要更改所有查询。

您无法真正创建经济的方式。您必须从数据库中获取完整的记录列表,因为无法从MySQL中知道记录的位置


根据您的排序、数据更改的频率,您可以将记录指定为其在列中的位置:将列位置添加到正在查询的表中。这可能在所有情况下都不可行。

在s子选择中使用类似的查询

SELECT s.row, s.RECORD, YOUR_OTHER_FIELDS...
FROM (SELECT @row := 0) cnt
  JOIN (SELECT @row := @row + 1 row, RECORD, ...YOUR QUERY WITH ORDER BY ...) s
WHERE s.RECORD = <desired record number>
正如预期的那样,行的值随您在子选择中使用的顺序而变化

它将变量初始化折叠到查询中,因此这只是一条语句。
它也不依赖于行的自然顺序或分布,只要它们返回的顺序与您指定或省略的顺序相同。

如果这是您经常使用的,我认为创建一个。我们可以使用inside来迭代结果,并获得所需项目的位置。我认为这会更快,它不必迭代到所有的记录,也不需要子查询。我认为这更经济,您可以使用order、join和任何您需要的功能

DELIMITER $$


CREATE FUNCTION position ( looking_for INT ) 
 RETURNS INT
READS SQL DATA
BEGIN
  -- First we declare all the variables we will need
  DECLARE id   INT;
  DECLARE pos   INT;
  SET pos=0;
  -- flag which will be set to true, when cursor reaches end of table
  DECLARE exit_loop BOOLEAN;         

  -- Declare the sql for the cursor
  DECLARE pos_cursor CURSOR FOR
    SELECT id  
    FROM your_table
    --you can use where, join, group by, order and whatever you need 
 --end of query

  -- Let mysql set exit_loop to true, if there are no more rows to iterate
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = TRUE;

  -- open the cursor
  OPEN example_cursor;

  -- marks the beginning of the loop
  example_loop: LOOP

    -- read the id from next row into the variable id
    FETCH  pos_cursor INTO  id;
    -- increment the pos var
    SET pos=pos+1;

    -- check if we found the desired item, 
    -- if it has been set we close the cursor and exit 
    -- the loop
    IF id=looking_for THEN
        CLOSE example_cursor;
        LEAVE example_loop;
    END IF;


    -- check if the exit_loop flag has been set by mysql, 
    -- if it has been set we close the cursor and exit 
    -- the loop
    IF exit_loop THEN
        CLOSE example_cursor;
        LEAVE example_loop;
    END IF;

  END LOOP example_loop;
 RETURN pos;
END $$

DELIMITER ;
只需创建一次函数,要使用它,只需使用以下sql:

CALL position(ID_OF_THE_ITEM_YOU_ARE_LOOKING_FOR);
并返回项目的位置,即返回行集的位置[0][0]

当然,您可以创建一个函数来比较名称、任何其他字段甚至多个字段,而不是id


如果查询总是不同的,那么您不能使用函数,但仍然可以使用游标,语法将是相同的。您可以在PHP中构建游标,让pos成为使用@pos的系统变量,并且在任何情况下,只需添加查询的特定sql,即声明pos_游标和-end of query之间的部分

X记录是什么意思?你是说第18张唱片在第2页吗?我是说第2页有ID为18的唱片,或者像标题Hello这样的唱片。这些记录可以用不同的方式进行排序。因此,我不能只计算itRecord is recordnumber/perPageYou可以使用添加的筛选器重新运行查询,以缩小结果范围,但除此之外,您必须搜索整个结果,而不仅仅是有限的结果one@WaygoodJavascript分页不是一个好的选择。如果我有10k记录,我必须加载所有10k并研究大量数据!使用php/js分页,我必须在所有页面中查找。这是我想要避免的。这个方法似乎是我需要的!但是如果我在子查询中使用连接,结果将失去顺序。例如:设置@rank=0;选择*从选择pt.id、pt.attr\u代码、pal.attribute\u标签、pt.is\u required、pt.is\u locked、pt.is\u visible、pt.is\u Compariable、@rank:=@rank+1作为fm\u产品属性的等级作为pt内部连接fm\u产品属性作为pt.id上的pal数据=pal.attributeid和pal.languageid=1按id分组按pt.attr\u代码ASC sq排序;使用此查询,order语句将被忽略,记录将获得默认ordinationNo,结果将按照我的意愿进行排序,但rank变量不在后面。您有必要在内部查询中按id分组吗?不,计数将为任何排序返回相同的结果。这是正确的答案。首先计算行数,直到找到记录为止,然后除以所需的分页数。有rank方法,但它跳过了顺序
当记录被排序时。我尝试过这个方法,虽然它有效,但出于某种原因,它似乎以相反的顺序返回行数。这是正确的行为吗?如果有,是否有解决方法?在子选择之外是否有group by或order by?是的,我有。我通过改变一些事情解决了这个问题。
CALL position(ID_OF_THE_ITEM_YOU_ARE_LOOKING_FOR);