使用列值作为计数限制结果数

时间:2017-01-15 15:10:39

标签: php mysql

我有两个查询,一个将从主表中获取一个ID列表,另一个将获取另一个表中与该ID相关的所有记录。

我想将其拆分为结果页面,但我的谷歌搜索只出现在想要每列值有一定数量结果的人身上,而不是想要通过它限制总体数量的人

主表有一个包含记录数的列,因此实际上不需要读取另一个表。该限制将用作最小值,因此如果在限制之后当前组中仍有剩余记录,则它将继续显示它们。这可以以某种方式计算为偏移的一部分,因此它可以从正确的位置开始。

这是我的意思的一个例子:

表1:

ID | GroupID | Value
1  |    1    |   x
2  |    1    |   x
3  |    2    |   x
4  |    2    |   x
5  |    2    |   x
6  |    3    |   x
   ...

表2(此问题不需要知道的内容):

1

如果限制为3,例如,21都应显示在第一页上,因为只有3本身处于限制之下。然后,下一页将从$page = 2; $limit = 40; $count = 0; $current_page = 1; $query = 'SELECT ID, Records FROM table1'; $stmt = $conn->prepare($query); $stmt->execute(); while($row = $stmt->fetch(PDO::FETCH_ASSOC)){ $count += $row['Records']; if($count > $limit){ $current_page ++; $count = 0; if($current_page == $page){ $start_id = $row['ID']; break; } } } 开始,这将占据整个页面。

我可以手动计算使用PHP,直到达到极限,但如果有很多页面可能最终会变慢(我不知道mysql在这方面是否会更好) 。以下是一个快速举例说明如何获得偏移:

 <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />

    <meta-date 
      android:name="com.google.android.maps.v2.API_KEY"   
      android:value="@string/google_maps_key"/>

   <meta-data 
      android:name="com.google.android.geo.API_KEY"  
      android:value="@string/google_maps_key"/>

3 个答案:

答案 0 :(得分:2)

更新

您正在寻找“自定义”Pagination。因此,如果您计划从一个页面跳到另一个页面,则无法使用硬编码的$page$current_page值。当您在特定页面上时,应该动态生成这些值。实际上,您应该在URL的查询部分中包含 ID 列值,以便分页链接可以满足您的业务逻辑。

假设您的 ID 列值从1开始,您的代码应如下所示:

$id = isset($_GET['id']) && is_numeric($_GET['id']) ? $_GET['id'] : 1;
$limit = 40;

// Display query results based on particular ID number
$query = 'SELECT ID, Records FROM table1 WHERE ID >= ' . $id;
$stmt = $conn->prepare($query);
$stmt->execute();
$rowCount = $stmt->rowCount();
if($rowCount){
    $total = 0;
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
        if($total <= $limit){
            $total += $row['Records'];
            // Display $row details here
        }else{
            // Get the next $id value
            $id = $row['ID'];
            break;
        }
    }
}

// Display relevant ID links
$query = 'SELECT * FROM table1';
$stmt = $conn->prepare($query);
$stmt->execute();

$idArr = array();
$total = 0;
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    if($total == 0){
        $idArr[] = $row['ID'];
    }
    if($total <= $limit){
        $total += $row['Records'];
    }else{
        $total = 0;
    }
}

foreach($idArr as $idValue){
    if($idValue == $id){
        echo '<a>'.$idValue.'</a> ';
    }else{
        echo '<a href="?id='.$idValue.'">'.$idValue.'</a> ';
    }
}

旁注:如果表格的 ID 列值未从1开始,请使用单独的查询来获取第一个 ID 值并更新以下语句

$id = isset($_GET['id']) && is_numeric($_GET['id']) ? $_GET['id'] : <FIRST_ID_VALUE>;

答案 1 :(得分:1)

如果您只需要创建“下一步”按钮,可以尝试这种方式:

select t1.ID, t1.Records
from table1 t1
left join table1 t2
    on  t2.ID < t1.ID
    and t2.ID > :last_selected_id_1
where t1.ID > :last_selected_id_2
group by t1.ID, t1.Records
having coalesce(sum(t2.Records), 0) < :limit
order by t1.ID

:last_selected_id_x是当前页面的最后一个ID或第一页的0

http://rextester.com/FJRUV28068

您可以使用MySQL会话变量来创建页面链接:

select page, min(ID) as min_id, max(ID) as max_id
from (
    select ID
         , @page := case when @sum = 0 then @page + 1 else @page end as page
         , @sum  := case when (@sum + Records) >= :limit
             then 0 
             else @sum + Records
         end as sum
    from table1
    cross join (select @sum := 0, @page := 0) initvars
    order by ID
) sub
group by page

结果如下:

page | min_id | max_id
   1 |      1 |      2
   2 |      3 |      3 
   3 |      4 |      4 

http://rextester.com/LQVJWP18655

请注意,正式(截至文档)不建议使用类似的会话变量(在一个语句中读取和写入)。功能版本可能会破坏您的代码。

答案 2 :(得分:1)

这是我最终得到的结果,我最终根据Rajdeeps的答案进行了调整,但进行了调整,以便它可以进行排序。

$query = 'SELECT ID, Records FROM table1 ORDER BY something';
$stmt = $conn->prepare($query);
$stmt->execute();
$id_array = array(); // For storing each ID
$current_ids = array(); // For storing the current ID pages
$initial_ids = array(); // For storing the first page, in case the page is too high

$count = 0;
$current_page = 1;
while($row = $stmt->fetch(PDO::FETCH_ASSOC)){
    $already_reset = false;

    // Move the session to the next page if it's more over the limit than under
    // For example, if a limit of 10 has 6 records already, and the next ID is 9 records, then start a new page
    if($id_array and $count + $row['Records'] / 2 > $max_links){
        array_push($id_array, $last_id);
        $current_page ++;
        $count = 0;
        $already_reset = true; // Set a marker so that if this ID is larger than the limit then don't start a 2nd new page
    }

    // Backup the first results in case page is too high and needs to be reset to 1
    if($current_page == 1){
        array_push($initial_ids, $row['ID']);
    }

    $count += $row['Records'];

    // The values that appear here are the results for the selected page
    // They may not be in sequence so store the individual IDs
    if($_GET['page'] == $current_page){
        array_push($current_ids, $row['ID']);
    }

    // Start a new page if over the limit
    if($count > $max_links and !$already_reset){
        $current_page ++;
        $count = 0;
        array_push($id_array, $row['ID']);
    }
    $last_id = $row['ID'];
}
array_push($id_array, $last_id);
$total_pages = count($id_array);

// If page is invalid revert to default
if(!$current_ids){
    $current_ids = $initial_ids;
    $_GET['page'] = 1;
}

$_GET['page'] = max(1, min($total_pages, intval($_GET['page'])));

$current_ids是当前页面的ID数组,$total_pages非常自我解释。