0

他の人がこの状況をどのように処理するのか...そして、この状況にDon't Repeat Yourself (DRY)の原則を適用する方法を考えています.

月を列として表示するために、T-SQL で常に PIVOT または CASE ステートメントを作成していることに気づきました。通常、(1) 日付フィールドと (2) 値フィールドを含むいくつかのフィールドがあります。ASPX ページまたは Reporting Services を介してこれをユーザーに提示する場合、このパターンを作成するには、最後の右端の 14 列が必要です。

[年],[1月],[2月],[3月],[4月],[5月],[6月],[7月],[8月],[9月],[10月],[11月],[12月] ]、[合計]

year は int としての年であり、他のすべてのフィールドはその月の合計値フィールドです (その年の合計値フィールドである [Total] を除く)。

これを処理するための再利用可能な方法を見つけたいと思います。すべての提案を受け入れる (T-SQL / ANSI SQL)

4

5 に答える 5

3

これはあなたが探しているものではありませんが、私は多くの繰り返しUNPIVOTを行いました。通常、私はこれをある種の標準化された命名でコード生成し、CTEを多用します。

WITH P AS (
    SELECT Some Data
            ,[234] -- These are stats
            ,[235]
    FROM Whatever
     )
,FINAL_UNPIVOTED AS (
    SELECT Some Data
            ,[STAT]
    FROM P
    UNPIVOT (
        STAT FOR BASE IN ([234], [235]) 
    ) AS unpvt
    WHERE STAT <> 0
)
SELECT Some Data
              ,CONVERT(int, FINAL_UNPIVOTED.[BASE]) AS [BASE]
              ,FINAL_UNPIVOTED.[STAT]
FROM FINAL_UNPIVOTED

テーブルまたはビューを調べて、次のようなものを使用することにより、codegenを実行できます。

DECLARE @sql_unpivot AS varchar(MAX)
SELECT @sql_unpivot = COALESCE(@sql_unpivot + ',', '') + COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'whatever'

そしてコードをテンプレート化する:

SET @template = '
    WITH P AS (
        SELECT Some Data
                ,{@sql_unpivot}
                  FROM Whatever
         )
    ,FINAL_UNPIVOTED AS (
        SELECT Some Data
                ,[STAT]
        FROM P
        UNPIVOT (
            STAT FOR BASE IN ({@sql_unpivot}) 
        ) AS unpvt
        WHERE STAT <> 0
    )
    SELECT Some Data
                  ,CONVERT(int, FINAL_UNPIVOTED.[BASE]) AS [BASE]
                  ,FINAL_UNPIVOTED.[STAT]
    FROM FINAL_UNPIVOTED
'
SET @sql = REPLACE(@template, '{@sql_unpivot}', @sql_unpivot)

もちろん、このコードを動的に実行したり、SPを作成して作成したりすることもできます。また、一時的に作成したビューまたはテーブルを交換して、インラインのメタデータを取得することもできます。

テーブル値関数とOUTERAPLYテクニックに関するコメントを参照してください。

于 2009-01-20T23:26:15.537 に答える
1

遅くなりましたが、明らかな何かが欠けている可能性がありますが、月ごとの行を含む Months テーブルはそれを行うのに役立ちますか?

于 2009-01-20T22:28:38.507 に答える
1
/* I leave year and month separate so you can use "real" Months or Fiscal Months */

CREATE FUNCTION [dbo].[fn_MonthValueColumns] 
(   
    @year int,
    @month int, 
    @measure int 
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT @year as [Year],
        CASE WHEN @month = 1 THEN @measure ELSE 0 END AS [Jan], 
        CASE WHEN @month = 2 THEN @measure ELSE 0 END AS [Feb], 
        CASE WHEN @month = 3 THEN @measure ELSE 0 END AS [Mar], 
        CASE WHEN @month = 4 THEN @measure ELSE 0 END AS [Apr], 
        CASE WHEN @month = 5 THEN @measure ELSE 0 END AS [May], 
        CASE WHEN @month = 6 THEN @measure ELSE 0 END AS [Jun], 
        CASE WHEN @month = 7 THEN @measure ELSE 0 END AS [Jul], 
        CASE WHEN @month = 8 THEN @measure ELSE 0 END AS [Aug], 
        CASE WHEN @month = 9 THEN @measure ELSE 0 END AS [Sep], 
        CASE WHEN @month = 10 THEN @measure ELSE 0 END AS [Oct], 
        CASE WHEN @month = 11 THEN @measure ELSE 0 END AS [Nov], 
        CASE WHEN @month = 12 THEN @measure ELSE 0 END AS [Dec], 
        @measure AS [Total]
)

  /* 
   use a group by after your own CROSS APPLY to roll-up SUMs for the last 13 fields. 

   this function and a CROSS APPLY against 100000 records ran in 3 seconds.
   for what I am doing, I can live with that performance.
  */
于 2009-01-21T16:56:13.607 に答える
0

ビューを使用するのはどうですか?

常に同じテーブル/テーブルのグループを使用する場合は、ビューが理にかなっています。警告: 大きなテーブルの小さなセクションを使用する場合は、このようなビューに注意してください。ビューによって、オプティマイザーがその仕事を実行できなくなる可能性があります。

于 2009-01-21T12:41:42.747 に答える
0

@Justiceがコメントで述べたように、DRY は通常、再利用可能なコードを指します。これは、SQL ではなく SQL クライアントの言語ではるかに簡単です。あなたがその選択肢を受け入れているなら (そして、そうでないかもしれません)、MyBatisのようなデータマッパーを検討してください。オブジェクトへの抽出はやり過ぎかもしれませんが、SQL スニペットを作成してさまざまなクエリで再利用する機能は、求めているもののように思えます。

于 2010-07-07T15:04:14.263 に答える