3

Urggggg!私は長い間これに苦労してきました!MySQLでそれを行うのはとても簡単ですが、SQLServerではできません:(

これは、すべて一緒に結合する必要がある簡略化されたテーブルです。

ここに画像の説明を入力してください

内部結合構文を使用してそれらすべてを組み合わせると、将来ページングに使用するクエリを作成する必要があります(ところで、PHP)。2012年10月1日から2012年10月30日までの間に撮影されたすべてのID、名前、日付の情報と、1ページあたり20人が必要だとします。

ここで目標を達成するための最も簡単なクエリは何でしょうか?(私はNOT INを試しましたが、それはとてもバグが多かったので、「NOTIN」のものに慣れていません...)

パフォーマンス速度は無視してかまいません。

ありがとうございました!

4

9 に答える 9

6

これは、SQLServer2005以降で行う方法です。

SELECT ID, Name, Photo, CreatedDate, rowNum, (rowNum / 20) + 1 as pageNum
FROM (
    SELECT a.ID, a.Name, b.Photo, c.Created_Date
       , Row_Number() OVER (ORDER BY c.Created_Date ASC) as rowNum
    FROM a
       JOIN b ON a.ID = b.ID
       JOIN c ON c.photo = b.photo
    WHERE c.Created_Date BETWEEN '2012-01-1' AND '2012-10-30'
) x
WHERE (rowNum / 20) + 1 = 1

ページ番号を計算するために少し整数除算のトリックを使用していることに注意してください。

2005年以前には、残念ながらrow_number()がないため、ID列を持つ中間テーブルを使用します。

    SELECT a.ID, a.Name, b.Photo, c.Created_Date
       , identity(int,1,1) as rowNum
    INTO t
    FROM a
       JOIN b ON a.ID = b.ID
       JOIN c ON c.photo = b.photo
    WHERE c.Created_Date BETWEEN '2012-01-1' AND '2012-10-30'
    ORDER BY c.Created_Date ASC
    GO

    ALTER TABLE t ADD pageNum AS rowNum / 20
    GO

    SELECT ID, Name, Photo, Created_Date, rowNum
    FROM t
    WHERE pageNum = 1 
于 2013-03-14T23:19:14.427 に答える
4

これが私がずっと前にそれをした方法です。

    SELECT * FROM (
      SELECT TOP y * FROM (
           SELECT TOP x * FROM sometable
           ORDER BY somefield ASC
      )
      ORDER BY somefield DESC)
ORDER BY somefield

最も内側のクエリであるSELECTTOPxは、最初のx行数を取得し、2番目のクエリであるSELECT TOP yは、x行の最後のyを取得し、最も外側のクエリであるSELECT *は、結果を正しい順序で配置します。

これがその仕組みを説明するブログ投稿ですこれは私が2006年に書き戻したブログ記事ですhttp://code.rawlinson.us/2006/12/t-sql-query-paging.html

tl; dr; 投稿のはこの段落からのものです:

たとえば、最初のページが必要だとすると、上位20件の結果が得られます。これは非常に簡単です。SELECTTOP20を使用するだけです…。しかし、2ページ目以降はどうですか?21〜40個のアイテムをどのように入手しますか?想像以上に簡単です。実際に取得しようとしているのは、上位x件の結果の下位yです。別の方法で見るには、上位x件の結果の上位yを逆順に並べます。

x値とy値を計算してクエリに提供する方法はあなた次第です。

于 2014-02-13T18:47:18.087 に答える
3

Microsoftは、 「OFFSET」と「FETCH」を使用して、SQLServer2012以降にネイティブページング機能を追加しました。この機能は次のように使用できます。

-- Skip the first 500 rows and return the next 100
SELECT *
FROM TableName
ORDER BY [ID]
    OFFSET 500 ROWS
    FETCH NEXT 100 ROWS ONLY;

OFFSET __and句にはFETCH NEXT __、(上記のように)定数値を指定するか、変数、式、または定数スカラーサブクエリを指定できます。

于 2015-07-23T11:54:06.993 に答える
2

Sql Server 2008+ AdventureWorksデータベースでこれを試してください

DECLARE @PageIndex INT, @RowsPerPage INT
DECLARE @StartRow INT, @EndRow INT;

SET @PageIndex = 1;
SET @RowsPerPage = 500;
SET @StartRow = ((@PageIndex - 1) * @RowsPerPage) + 1;
SET @EndRow = @StartRow + @RowsPerPage - 1;

--append#1
WITH PAGE_ROWS
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY OrderDate DESC, SalesOrderNumber ASC) AS ROW_NO
    , COUNT(*) OVER() AS TOTAL_ROWS
    , *
FROM( 
    --working query
    SELECT S.SalesOrderID
        , S.SalesOrderNumber
        , S.OrderDate
        , S.DueDate
        , S.ShipDate
        , S.Status
        , S.PurchaseOrderNumber
        , C.AccountNumber
        , P.FirstName, P.MiddleName, P.LastName
    FROM [Sales].[SalesOrderHeader] AS S
        LEFT OUTER JOIN [Sales].[Customer] AS C ON C.CustomerID=S.CustomerID
        LEFT OUTER JOIN [Person].[Person] AS P ON P.BusinessEntityID=C.PersonID
--append#2
) AS Src)
SELECT CEILING(TOTAL_ROWS/ CAST(@RowsPerPage AS DECIMAL(20,2))) AS TOTAL_PAGES
    ,*
FROM PAGE_ROWS
WHERE ROW_NO BETWEEN @StartRow AND @EndRow
ORDER BY OrderDate DESC, SalesOrderNumber ASC
于 2014-02-13T17:22:54.010 に答える
1
ALTER  Proc [dbo].[Sp_PagingonTable] 
@SearchText varchar(255) = null,
@ChannelName varchar(255)= null,
@ChannelCategory varchar(255)= null,
@ChannelType varchar(255)= null,
@PageNo int,
@PageSize int,
@TotalPages int output
As
DECLARE  @VariableTable TABLE
(
Rownumber INT,
ReferralHierarchyKey BIGINT, 
ReferralID VARCHAR(255), 
ChannelDetail VARCHAR(255),     
ChannelName VARCHAR(255),
ChannelCategory VARCHAR(255),
ChannelType VARCHAR(255)
)
 /*---Inserting Data into variable Table-------------*/
INSERT INTO @VariableTable
SELECT   
 ROW_NUMBER() OVER(ORDER BY [ColumnID) as Rownumber,*
 FROM [dbo].[TableName]
 WHERE (@SearchText IS NULL OR ChannelDetail LIKE '%' + @SearchText + '%')                                 And       (@ChannelName  IS NULL OR ChannelName  = @ChannelName )
/*--Applying Paging on filter Table--*/
SELECT 
        ReferralID
       ,ChannelDetail
       ,ChannelName
       ,ChannelCategory
       ,ChannelType 
    FROM 
        @VariableTable
WHERE Rownumber between (((@PageNo -1) *@PageSize)+1) and @PageNo *    @PageSize
 /*--Getting Total Pages After filter Table---*/
 SELECT @TotalPages =  (Count(*) + @PageSize - 1)/@PageSize FROM  @VariableTable
 SELECT @TotalPages
于 2014-02-06T11:00:29.823 に答える
1

渡されたクエリを変更する必要があり、元同僚による設計上の決定が非常に貧弱だったために使用しなければならないSQL UNIONステートメントでは機能しなかったことを除いて、TahaSiddiquiの回答が気に入りました。

一般的なSQLServerクエリは次のとおりです。

SELECT * FROM (
    select ROW_NUMBER() OVER (order by ID) as row_num, * FROM (
      <<Put Your Query Here>>
    ) AS tempTable1
) AS tempTable2 WHERE row_num >= ((pageNum -1) * pageSize) AND row_num < ((pageNum -1) * pageSize) + pageSize;

1ベースのページングを想定したJava関数を作成しました。

    public static String buildPagingQuery(String sqlStr, String sortExpression, int pageNum, int pageSize) {
        if (StringUtils.isBlank(sortExpression)) { //NOTE: uses org.apache.commons.lang.StringUtils
            sortExpression = " (select 0)";
        }

        int startIndex = ((pageNum - 1) * pageSize) + 1;
        int endIndex = startIndex + pageSize;

        StringBuilder sb = new StringBuilder();

        sb.append("SELECT * FROM (");
        sb.append("SELECT ROW_NUMBER() OVER (ORDER BY ");
        sb.append(sortExpression);
        sb.append(") as row_num, * FROM (");
        sb.append(sqlStr);
        sb.append(") as tempTable1 ");
        sb.append(") AS tempTable2  "); 
        sb.append("WHERE row_num >= ").append(startIndex);
        sb.append(" AND row_num < ").append(endIndex);

        return sb.toString();
    }

大きなテーブルでのパフォーマンスはまだ確認していません。

于 2014-09-08T16:35:28.280 に答える
1

CTE(Common Table Expressions)でも同じことができます。まず、現在のページ番号と、フェッチする必要のある結果のオフセットを設定する必要があります。次に、ROW_NUMBERで結果セットを並べ替え、を使用して結果を保存する必要があります。 cte feature.thenは、ページサイズと行番号に対するオフセットで結果をフィルタリングします。SQLクエリは次のとおりです

DECLARE @PageSize INT=1 ,@PageNumber INT=2

DECLARE @Offset int =(@PageSize * (@PageNumber - 1))+1

;WITH Results_CTE AS
(

    SELECT *,
                   ROW_NUMBER() OVER (ORDER BY FieldName) AS RowNum
    FROM TABLENAME
  )  

  SELECT *
  FROM Results_CTE
  WHERE RowNum>=@Offset AND RowNum < @Offset + @PageSize

END

https://amonghorizo​​n.blogspot.com/2020/07/sql-server-query-for-pagination-control.html

于 2020-10-14T13:08:34.983 に答える
0

次のクラスのメソッドを使用できます

internal class PagingHelper
{
    public static String ParseQueryForPagingAndSorting(String strSQL, string SortExpression, int StartIndex, int EndIndex)
    {
        if (String.IsNullOrEmpty(SortExpression))
            SortExpression = " (select 0)";
        StringBuilder sb = new StringBuilder();
        sb.Append("select * from (");
        sb.Append(" select ROW_NUMBER() OVER (ORDER BY " + SortExpression + ") AS row_num,");
        int index = strSQL.ToLower().IndexOf('t', 0);
        sb.Append(strSQL.Substring(index + 2));
        sb.Append(")");
        sb.Append(" AS TempTable");
        sb.Append(" where row_num>=" + StartIndex.ToString() + " AND row_num<=" + EndIndex.ToString());
        return sb.ToString();
    }
    public static String ParseQueryForCount(String strSQL)
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("select count(*) from");
        sb.Append("(");
        sb.Append(strSQL);
        sb.Append(")");
        sb.Append(" AS TempTable");
        return sb.ToString();
    }
}
于 2014-04-05T19:54:40.510 に答える
-1

SQLServer2012でこれを行うために私が見つけた別の方法があります

http://raresql.com/2012/07/01/sql-paging-in-sql-server-2012-using-order-by-offset-and-fetch-next/

于 2014-01-22T11:43:24.237 に答える