0

SQL Server ストアド プロシージャを使用して、WPF データグリッドのデータ ソースとして使用するデータ テーブルを生成しています。データは親 [Sample] 子 [SampleConstituent] 関係の 2 つのテーブルにあり、PIVOT を使用して子テーブルのデータ レコードの列を生成しています。クエリはパラメーターを使用して、データグリッドに返されるレコードをフィルター処理できるようにします。

私の問題は、最新のレコードに基づいてクエリから TOP N の結果セットを返したいということです。次のストアド プロシージャがあり、データが常に最も古いレコードが最初に返されることを除いて、すべてが機能します。したがって、TOP Nフィルターは最新のレコードではなく、最も古いレコードを返します。Sample.SampleDateTime並べ替えたい親テーブルの列です。

私は初心者の脳が結び目であるほど多くの反復を試みました!

ALTER PROCEDURE [dbo].[spSampleDisplayAllParams] 
-- Add the parameters for the stored procedure here
@fromDate DATE = '2013-01-01', 
@toDate DATE = '2100-01-01',
@ProductName NVARCHAR(50) = '%',
@SampleNumber NVARCHAR(50) = '%',
@numSamples NVARCHAR(50) = 200
AS
BEGIN
SET NOCOUNT ON;

DECLARE @cols AS NVARCHAR(MAX),
@query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(ConstituentName) 
                from SampleConstituent
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')
PRINT @cols

set @query 
  = 'SELECT top (' + @numSamples + ') * from  
     (SELECT TOP 100 PERCENT  s.SampleID, s.SampleNumber, s.SampleDateTime, s.ProductName, sc.ConstituentName, sc.ConstituentValue
FROM         dbo.Sample s INNER JOIN
                  dbo.SampleConstituent sc ON s.SampleID = sc.SampleID
WHERE (s.Active = 1) AND 
(s.ProductName Like  ''' + @ProductName + ''') AND
(s.SampleNumber Like  ''' + @SampleNumber + ''') AND
(s.SampleDateTime BETWEEN ''' + CONVERT(nvarchar(24), @FromDate, 121) +''' AND'''+     CONVERT(nvarchar(24), @ToDate, 121) +''')
ORDER BY s.SampleDateTime        )     x
     pivot 
     (
        max(ConstituentValue)
        for ConstituentName in (' + @cols + ')
     ) p  '

execute(@query)
END
4

2 に答える 2

2

ご注文は TOP 100 PERCENT 内にあります。この場合、どの行を含めるかを指示するために ORDER BY が使用されていますが、すべての行が必要だと言ったので、SQL Server は賢く、TOP と ORDER BY の両方をスローします。計画を見て、きっとどこにもソートはありません。これ:

SELECT * FROM 
  (SELECT TOP 100 PERCENT something FROM somewhere ORDER BY something) AS x;

以下とまったく同じです:

SELECT * FROM 
  (SELECT something FROM somewhere) AS x;

どちらの場合も、SQL Server は最終結果を順序付けするように指示されません。そうではなく、代わりに、あなたの心を読もうとするのではなく、最も効率的な順序を選択します。

並べ替えたい場合は、@Sonam が特定したように、最も外側のクエリに配置する必要があります。ここにいくつかの背景情報があります:

参考までに、SQL インジェクションから身を守り、適切なパラメーター化されたクエリを使用するために最善を尽くす必要があります。繰り返しますが、@Sonamの回答から何も取りませんが、これは次のように優れています。

SELECT @sql = N'SELECT TOP (@numSamples) * FROM 
(
  SELECT s.SampleID, s.SampleNumber, s.SampleDateTime, 
         s.ProductName, sc.ConstituentName, sc.ConstituentValue
  FROM dbo.Sample AS s 
  INNER JOIN dbo.SampleConstituent AS sc 
  ON s.SampleID = sc.SampleID
  WHERE (s.Active = 1) AND 
  (s.ProductName LIKE @ProductName) AND
  (s.SampleNumber LIKE @SampleNumber) AND
  (s.SampleDateTime >= @FromDate AND s.SampleDateTime < DATEADD(DAY, 1, @ToDate)
) AS x
PIVOT
(
  MAX(ConstituentValue) FOR ConstituentName IN (' + @cols + ')
) AS p
ORDER BY SampleDateTime DESC;';

DECLARE @params NVARCHAR(MAX) = N'@numSamples INT, @fromDate DATE, ' +
  '@toDate DATE, @ProductName NVARCHAR(50), @SampleNumber NVARCHAR(50)';

EXEC sp_executesql @sql, @params, @numSamples, @fromDate, @toDate,
  @ProductName, @SampleNumber;

@colsの作成には、選択した日付範囲 (または where 句の他の部分) のテーブルに表示されない構成銘柄が含まれる可能性があることにNULL注意してください。日付が選択されている場合、それらの条件の一部をそのクエリにも追加することができます。

于 2013-09-06T18:36:55.917 に答える