sql >> データベース >  >> RDS >> Sqlserver

LINQ to SQL Take w / o Skipは、複数のSQLステートメントを引き起こします

    まず、Takeバグの理由。

    取るだけの場合 、クエリトランスレータはtopを使用します。子コレクションに参加することでカーディナリティが破られた場合、Top10は正しい答えを出しません。したがって、クエリトランスレータは子コレクションに参加しません(代わりに子を要求します)。

    スキップして取る場合 、次に、クエリトランスレータは親行に対していくつかのRowNumberロジックを使用します...これらの行番号により、各親に5つの子があるため、実際には50レコードであっても、10の親を取ることができます。

    スキップ(0)して取る 、スキップは翻訳者によって非操作として削除されます-スキップと言ったことがないのと同じです。

    これは、現在の場所(Skip and Takeと呼ぶ)から「単純な回避策」への概念的な飛躍になります。私たちがする必要があるのは、翻訳者が非操作としてSkip(0)を削除できないポイントで翻訳を強制的に実行することです。スキップを呼び出し、後でスキップした番号を指定する必要があります。

    DataClasses1DataContext myDC = new DataClasses1DataContext();
      //setting up log so we can see what's going on
    myDC.Log = Console.Out;
    
      //hierarchical query - not important
    var query = myDC.Options.Select(option => new{
      ID = option.ParentID,
      Others = myDC.Options.Select(option2 => new{
        ID = option2.ParentID
      })
    });
      //request translation of the query!  Important!
    var compQuery = System.Data.Linq.CompiledQuery
      .Compile<DataClasses1DataContext, int, int, System.Collections.IEnumerable>
      ( (dc, skip, take) => query.Skip(skip).Take(take) );
    
      //now run the query and specify that 0 rows are to be skipped.
    compQuery.Invoke(myDC, 0, 10);
    

    これにより、次のクエリが生成されます。

    SELECT [t1].[ParentID], [t2].[ParentID] AS [ParentID2], (
        SELECT COUNT(*)
        FROM [dbo].[Option] AS [t3]
        ) AS [value]
    FROM (
        SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID]) AS [ROW_NUMBER], [t0].[ParentID]
        FROM [dbo].[Option] AS [t0]
        ) AS [t1]
    LEFT OUTER JOIN [dbo].[Option] AS [t2] ON 1=1 
    WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2
    ORDER BY [t1].[ROW_NUMBER], [t2].[ID]
    -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
    -- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0]
    -- @p2: Input Int (Size = 0; Prec = 0; Scale = 0) [10]
    -- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1
    

    そして、ここが私たちの勝ちです!

    WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p1 + @p2
    


    1. DBMS_SCHEDULER.CREATE_JOBプロシージャを使用してプロシージャを実行する方法

    2. IntegrityError:一意性制約とnull以外の違反を区別する

    3. PostgreSQLで数値をフォーマットする方法

    4. MariaDBとMySQLのクラウドディザスタリカバリ