none
TOPではなく、指定件数目のレコードを取得する方法について RRS feed

  • 質問

  • SQLに関する質問です。

    Table: X(列Y)
    ※YはPK

    に対して、Z件目のレコードを取得する方法はありませんでしょうか?

    1件目からZ件目であれば、

    =====

     SELECT TOP(Z) * FROM X

    =====

    とか書くのですが、
    Z件目だけ欲しい状況です。

    試しに
        SELECT TOP(1) Y
        FROM Z
        WHERE Y IN
        (
            SELECT TOP(Z) Y
            FROM X
        )
        ORDER BY Y DESC
    と記載したら、一番最後のレコードが取れてしまいました。

    こちらの意図としては、
    XからZ件取得して、それをY列で降順に並び替えてTOP(1)としたかったのですが・・・

    ヒントなどを用いて、サブクエリ使用を強制的に指定する方法とかはあるのでしょうか?
    2009年1月15日 10:34

回答

  • すでに、良い解答がでていますが別手段を提示します。

     

    が、この方法はパフォーマンス問題の原因になりうるので参考にとどめておくのが将来の幸福につながると思います^^;

     

    http://msdn.microsoft.com/ja-jp/library/ms188055.aspx

    SQL Server 2008 オンライン ブック (2008 年 8 月)
    EXCEPT および INTERSECT (Transact-SQL)

     

    考え方は、TOP(Z)とTOP(Z-1)を比較して差分の一件がZ番目ですよ!て方法です。

     

    SELECT TOP(Z) * FROM X

    EXCEPT

    SELECT TOP(Z-1) * FROM X

     

    これの問題点は、Zが10万件とかになると1件を取得するためだけに10万件と9万9999件SELECTした結果を比較して・・・と激しい処理になることです。

    力業でスマートじゃないですが、まぁEXCEPTってのがありますよっという紹介だと思って読み流してください。

    2009年1月15日 13:24
  •  YOSHIKAZU さんからの引用

    こちらの意図としては、
    XからZ件取得して、それをY列で降順に並び替えてTOP(1)としたかったのですが・・・

    試しに書かれた書き方だと以下で良いと思います。

     

    select top 1 Y from X where Y in (select top 10 Y from X
     order by Y) order by Y desc

     

    以下でも大丈夫でしょう。

     

    select top 1 Y from (select top 10 Y from X order by Y) T o
    rder by T.Y desc

    2009年1月15日 15:11
  • 皆様、ありがとうございます。
    ROW_NUMBER関数を使用して解決することが出来ました。


    2009年1月21日 2:07

すべての返信

  •  YOSHIKAZU さんからの引用
    Table: X(列Y)
    ※YはPK

    に対して、Z件目のレコードを取得する方法はありませんでしょうか?

     

    ROW_NUMBER を使えばできると思います。

     

    Code Snippet

    SELECT
        Y
    FROM (
        SELECT
            Y
            ,ROW_NUMBER() OVER (ORDER BY Y) AS RowNumber
        FROM
            X
    ) AS T
    WHERE
        RowNumber = Z

     

    ROW_NUMBER (Transact-SQL)

    http://msdn.microsoft.com/ja-jp/library/ms186734(SQL.90).aspx

    2009年1月15日 12:50
  • すでに、良い解答がでていますが別手段を提示します。

     

    が、この方法はパフォーマンス問題の原因になりうるので参考にとどめておくのが将来の幸福につながると思います^^;

     

    http://msdn.microsoft.com/ja-jp/library/ms188055.aspx

    SQL Server 2008 オンライン ブック (2008 年 8 月)
    EXCEPT および INTERSECT (Transact-SQL)

     

    考え方は、TOP(Z)とTOP(Z-1)を比較して差分の一件がZ番目ですよ!て方法です。

     

    SELECT TOP(Z) * FROM X

    EXCEPT

    SELECT TOP(Z-1) * FROM X

     

    これの問題点は、Zが10万件とかになると1件を取得するためだけに10万件と9万9999件SELECTした結果を比較して・・・と激しい処理になることです。

    力業でスマートじゃないですが、まぁEXCEPTってのがありますよっという紹介だと思って読み流してください。

    2009年1月15日 13:24
  •  YOSHIKAZU さんからの引用

    こちらの意図としては、
    XからZ件取得して、それをY列で降順に並び替えてTOP(1)としたかったのですが・・・

    試しに書かれた書き方だと以下で良いと思います。

     

    select top 1 Y from X where Y in (select top 10 Y from X
     order by Y) order by Y desc

     

    以下でも大丈夫でしょう。

     

    select top 1 Y from (select top 10 Y from X order by Y) T o
    rder by T.Y desc

    2009年1月15日 15:11
  • 皆様、ありがとうございます。
    ROW_NUMBER関数を使用して解決することが出来ました。


    2009年1月21日 2:07