2017-04-09 3 views
1

postgresqlで、いくつかのページ付けに使用される開始レコードIDに基づいてレコードの前と次のX個のレコードを取得できるクエリを使用しようとしています。 1つだけ次の、または前の取得はそれほど難しいことではありませんが、それは私が必要なものではありません。SQL - 次のXレコードと前のXレコードを取得する

私は近くにあるクエリをいくつか見つけましたが、これらのタイプの複雑なクエリを実行するためにPostgreSQLクエリについては十分にわかりません。

この質問は私が試してみたところ、IDの前と次の項目と、すべてを返しているようです。レコード。

しかし、それはWHERE句のようなIDを提供する開始点を与えることができ、存在する場合には10個の次のレコードと10個の次のレコードだけを得ることができる必要があります。これはsqlだけでも可能ですか?

SELECT 
    m.med_id AS id, 
    coalesce(
     LEAD(m.med_id) OVER (ORDER BY m.med_id DESC), 
     (select med.med_id from media as med order by med.med_id desc limit 1) 
) AS nextitemid, 
    coalesce(
     LAG(m.med_id) OVER (ORDER BY m.med_id DESC), 
     (select med.med_id from media as med order by med.med_id asc limit 1) 
) AS previtemid 
FROM media m 
WHERE m.post_type = 1 
ORDER BY m.med_id DESC LIMIT 20; 

これは、これを実現する任意のタイプのSQLソリューションです。

希望の出力私は、クエリで提供されたID開始点として50を与えられた100個のアイテムの例によると思います。

|previtemids|nextitemids| 
    49   51 
    48   52 
    47   53 
    46   54 
    45   55 
    44   56 
    43   57 
    42   58 
    41   59 
    40   60 

私は近づいてきましたが、1つのクエリで取得できませんでした。私のシナリオに近い回答は、一般的な回答よりも役立ちます。そこに例えば、10前の行が存在しない場合は、しかし:

+0

前のレコードを10個、次のレコードを10個、レコードごとに別々の行にしますか? – Alex

+0

Hmm良い質問@Alex PHPから配列に読み込む予定です。おそらく列が簡単かもしれませんか? –

+0

希望の出力例を投稿してください。 – Alex

答えて

0
with numbered as(
    select your_table.*, row_number() over(order by id) as rn from your_table 
) 
SELECT previous.id, next.id FROM 
(SELECT id, row_number() over(order by id) as inner_rn FROM numbered where rn between (select rn from numbered WHERE id = 12) - 5 and (select rn from numbered WHERE id = 12) -1) previous 
INNER JOIN 
(SELECT id, row_number() over(order by id) as inner_rn FROM numbered where rn between (select rn from numbered WHERE id = 12) + 1 and (select rn from numbered WHERE id = 12) + 5) next 
ON previous.inner_rn = next.inner_rn 

私は理解し修正する場合は、ここでこの

を必要とする12は次と前のXレコード

が(注意されstarting point providing an IDと5です次の10行です。欠落した値をNULLで埋める必要があります。次にINNER JOINの代わりにを使用してください)

+0

実際には正しい結果が得られませんでした。私が持っていた質問は、私が必要としていたものに少し近いものでした。ちょうど期待どおりに動作しません。 –

+0

これで、前と次のxidが異なる2つの列に必要ですか? (あなたの編集例のように) –

+0

私はそれが理想だろうと思う。 –

0

これはこれを使って0-1000の間の100の乱数を生成します。

SELECT 
    trunc(random()*1000) AS x 
FROM generate_series(1,100); 

ここでIDが80の場合、ここで70-90の範囲を見つけることができます。

SELECT * 
FROM (
    SELECT rank() OVER (ORDER BY x) AS dr, x 
    FROM (
    SELECT 
     trunc(random()*1000) AS x 
    FROM generate_series(1,100) 
) AS t 
) AS t 
WHERE dr BETWEEN 80-10 AND 80+10; 

dr | x 
----+----- 
70 | 702 
71 | 706 
72 | 718 
73 | 734 
74 | 751 
75 | 756 
76 | 774 
77 | 778 
78 | 805 
79 | 813 
80 | 829 
81 | 833 
82 | 839 
83 | 852 
84 | 853 
85 | 872 
86 | 884 
86 | 884 
88 | 892 
89 | 897 
90 | 905 
(21 rows) 

しかし、私はこれをしません。 IDと目的の行を渡してページングを行います。そして、前進することしか許さない。以前の結果をブラウザに保存します。

関連する問題