3

SQL Server 2008 R2 のストアド プロシージャ内で使用する必要がある奇妙な要件があります。

シーケンスの最初の要素を返す FIRST 集計関数が必要であり、それを withHAVING句で使用します。

例を挙げましょう:

DECLARE @fooTable AS TABLE(
    ID INT,
    CategoryName NVARCHAR(100),
    Name NVARCHAR(100),
    MinAllow INT,
    Price DECIMAL(18,2)
);

INSERT INTO @fooTable  VALUES(1, 'Cat1', 'Product1', 2, 112.2);
INSERT INTO @fooTable  VALUES(2, 'Cat2', 'Product2', 4, 12.34);
INSERT INTO @fooTable  VALUES(3, 'Cat1', 'Product3', 5, 233.32);
INSERT INTO @fooTable  VALUES(4, 'Cat3', 'Product4', 4, 12.43);
INSERT INTO @fooTable  VALUES(5, 'Cat3', 'Product5', 1, 13.00);

DECLARE @minAllowParam AS INT = 3;

SELECT ft.CategoryName, SUM(ft.Price) FROM @fooTable ft
GROUP BY ft.CategoryName;

ご覧のとおり、テーブルといくつかのダミー値があります。クエリ内でSELECT、カテゴリをグループ化し、製品の価格を合計します。

このクエリは次の結果を返します。

CategoryName     TotalPrice
---------------- ----------------
Cat1              345.52
Cat2              12.34
Cat3              25.43

ここで必要なのは次のようなものです。

SELECT ft.CategoryName, SUM(ft.Price) FROM @fooTable ft
GROUP BY ft.CategoryName
HAVING GetFIRST(MinAllow) >= @minAllowParam;

このようなクエリの場合、次の結果を選択できるはずです。

INSERT INTO @fooTable  VALUES(2, 'Cat2', 'Product2', 4, 12.34);
INSERT INTO @fooTable  VALUES(4, 'Cat3', 'Product4', 4, 12.43);
INSERT INTO @fooTable  VALUES(5, 'Cat3', 'Product5', 1, 13.00);

INSERT INTO @fooTable VALUES(1, 'Cat1', 'Product1', 2, 112.2);レコードはシーケンスの最初の要素であり、列の値は 2 であるため、MinAllowCat1ここでは範囲外にする必要があります。一方、INSERT INTO @fooTable VALUES(5, 'Cat3', 'Product5', 1, 13.00);record はMinAllowcolumn の値が 1 ですが、シーケンスの 2 番目の要素です。というわけで、Cat3が安心して選択できます。

注: MINorMAXは私が探しているものではありません!

この例は論理的には意味をなさないことはわかっていますが、一方では完全に意味があり、ここで説明するのが難しい状況があります。

何かご意見は?

編集:

CLR User-Defined Aggregate Function を作成することで、ここで必要なことを達成できると想定していますが、他に選択肢がある場合はこれを実行したくありません

4

4 に答える 4

3

どうですか

SELECT f1.CategoryName, SUM(f1.Price) 
FROM @fooTable AS f1
INNER JOIN (
    SELECT MinAllow, CategoryName
    FROM (
         SELECT MinAllow, CategoryName, ROW_NUMBER() OVER (PARTITION BY CategoryName ORDER BY ID) AS m
         FROM @fooTable
    ) AS f
    WHERE m = 1
) AS f2 ON f1.CategoryName = f2.CategoryName
WHERE f2.MinAllow >= @minAllowParam
GROUP BY f1.CategoryName

私はあまりエレガントなクエリを知りません。もう少し作業をすれば、少し調整できるかもしれません。

編集:わかりました、最も内側のサブクエリは不要です。これも機能するはずです:

SELECT f1.CategoryName, SUM(f1.Price) 
FROM @fooTable AS f1
INNER JOIN (
    SELECT MinAllow, CategoryName, ROW_NUMBER() OVER (PARTITION BY CategoryName ORDER BY ID) AS m
    FROM @fooTable
) AS f2 ON f1.CategoryName = f2.CategoryName
WHERE f2.m = 1 AND f2.MinAllow >= @minAllowParam
GROUP BY f1.CategoryName
于 2012-04-12T08:58:02.597 に答える
2

更新:読み取り可能なクエリ:

SELECT ft.CategoryName, SUM(ft.Price) 
FROM fooTable ft
    cross apply
    (
       select top 1 MinAllow
         from fooTable a
        where a.CategoryName = ft.CategoryName
        order by ID
    ) a
where a.MinAllow >= @minAllowParam
GROUP BY ft.CategoryName;

最初に(IDで?)MinAllow> = @minAllowParamを持つカテゴリをフィルタリングできます:

...
inner join 
(
   select 
   -- Add columns you might need
     CategoryName,
     Price
   from
     fooTable
   inner join
   (
     -- First ID in category
     select
       min(id) id
     from
       fooTable
     group by
       CategoryName
   ) firstID
   -- Back to all columns
     ON fooTable.ID = firstID.ID
   -- but only if category sequence starts properly
    AND fooTable.MinAllow >= @minAllowParam
) a
-- Allow MinAllow categories only
  ON fooTable.CategoryName = a.CategoryName
于 2012-04-12T08:51:48.930 に答える
1

パーティショニングを使用した ROW_NUMBER() を見てください。

http://msdn.microsoft.com/en-us/library/ms186734.aspx

于 2012-04-12T08:50:46.233 に答える
0

FIRST集計関数を実現するために私が知っている2つの方法があります。

ROW_NUMBER()

(WHERE ROW_NUMBER_COLUMN = 1)

http://msdn.microsoft.com/en-us/library/ms186734.aspx

SELECT ...., (SELECT TOP 1 FROM ... WHERE (outer table join) ORDER BY SOMETHING) AS [FIRST]
FROM ...
于 2012-04-12T08:56:20.647 に答える