1

次のデータセットがあります。

update (id, update_time)
1    <a timestamp>
2    <a timestamp>

item_update (update_id, item_id)
1    327
1    328
1    496
2    345
2    477

私がやりたいのは、ページに次のように表示することです。

2012 年 3 月 6 日:
327
328
496

2012 年 7 月 7 日:
345
477

多かれ少なかれ。問題は、データセットがかなり大きくなると予想されることです。1 ページにすべてを含めることはできません。ただし、任意の数に制限すると、グループが途中で切断されます。更新によってそれらを制限すると、あるページでは少なすぎ、別のページでは多すぎる可能性があります。

特定のアイテム数を超えずにできるだけ多くのグループ (更新) を取得できるように、結果セットを制限するにはどうすればよいですか?

4

4 に答える 4

1

The following query

select a.id, floor(ifnull(sum(b.update_count),0) / 50) as start_page
from updte as a
left join
    (select update_id, case when count(1) > 50 then 50 else count(1) end as update_count
     from item_update group by update_id) as b
  on a.id > b.update_id
group by a.id

will give you the page number that each update_id group should start on (assuming that we want to show no more then 50 items on page except when there is more than 50 items in group). Knowing start_page for each update_id you can display only relevant update_id from item_update.

于 2012-07-24T20:14:51.977 に答える
1

グループを分割したくない場合は、単純に

select update_id, count(*) cnt from item_update group by update_id;

これにより、各 update_id のカウントが得られます。次に、 update_ids をループし、累積がページの最大値に達する (または通過する) までループし、それらすべての update_ids に対して別のクエリを実行するだけです...

ただし、1 つの更新グループに 1 つの項目があり、次の更新グループに 1000 の項目があるというエッジ ケースがあるかもしれません...その場合、グループでページネーションを中断できるようにすることはおそらく理にかなっています...

page1

group1
  item1
  item2
  item3
group2
  item1
  item2

page2

group2
  item3
  item4
  etc...

次に、並べ替えで limit 句を使用するだけの問題です...

于 2012-07-24T19:58:31.263 に答える
0

きれいではありませんが、答えが見つかりました。

基本的に、次のように、最初update_idに item_update 内の一意のものをすべて見つける必要があります。

(SELECT * FROM 
    (SELECT update_id 
     FROM item_update
     WHERE update_id < :my_last_id_from_previous_page
     ORDER BY update_id DESC
     LIMIT 0, :limit
) as inner_query
GROUP BY update_id) as outer_query

その結果のテーブルには、返される必要があるすべてのグループが表示されるので、残りは簡単です。

SELECT item_id, update.id, update_time FROM outer_query
INNER JOIN item_update ON (item_update.update_id = outer_query.update_id)
INNER JOIN update ON (item_update.update_id = update.id)
于 2012-07-24T20:06:54.317 に答える
0

このソリューションを使用できます:

SELECT     b.update_time, a.item_id           
FROM       item_update a
INNER JOIN updte b ON a.update_id = b.id
LEFT JOIN  item_update c ON a.update_id = c.update_id
      AND  a.item_id <= c.item_id
GROUP BY   a.update_id, a.item_id
HAVING     COUNT(1) <= 2

句のは2、グループごとに制限するアイテムの数です (グループごとに最大nHAVINGによって制限されます)。デモを使用して、このソリューションをいじることができます。item_id

SQLFiddle デモ

2を に変更すると、33 月 6 日の結果がもう 1 つ得られることに注意してください。


結果を階層的に表示する場合は、次のようにします。

SELECT a.val
FROM
(
    SELECT     CONCAT('- - - -> ', a.item_id) AS val,
               CONCAT(b.update_time, a.item_id) AS orderfactor
    FROM       item_update a
    INNER JOIN updte b ON a.update_id = b.id
    LEFT JOIN  item_update c ON a.update_id = c.update_id AND a.item_id <= c.item_id
    GROUP BY   a.update_id, a.item_id
    HAVING     COUNT(1) <= 2

    UNION ALL

    SELECT DATE_FORMAT(update_time, 'On %M %e, %Y:'), 
           update_time
    FROM   updte
) a
ORDER BY a.orderfactor

SQLFiddle デモ

于 2012-07-24T20:01:41.243 に答える