2

SQL Server 2005/2008 を実行して、クエリを書き直して、よりクリーンでコンプライアンスを向上させ、悪い習慣を含めないようにしています。以前は多くのIFステートメントがありPIVOT、これを行っていましたが、今ではそれを達成するためのより良い方法を見つけたので、ほぼ完璧にするために最後のビットが必要です。

DECLARE @startdate DATETIME;
DECLARE @enddate DATETIME;
DECLARE @showstore INT;
DECLARE @showcashier INT;
DECLARE @showregister INT;
DECLARE @showdate INT;
DECLARE @sql NVARCHAR(MAX);
DECLARE @result0 NVARCHAR(MAX);

SET @startdate = '1/1/2012';
SET @enddate = '2/28/2013';
SET @showdate = 1;
SET @showstore = 0;
SET @showcashier = 1;
SET @showregister = 0;
SET @startdate = DATEADD(DAY, DATEDIFF(DAY, 0, @startdate), 0);
SET @enddate = DATEADD(DAY, DATEDIFF(DAY, 0, @enddate), 0);

SET @sql = N'CREATE TABLE ##a13 (' + SUBSTRING(
CASE WHEN @showdate = 1 THEN ',[Transaction Date] DATETIME' ELSE '' END + 
CASE WHEN @showstore = 1 THEN ',[Store ID] VARCHAR(10)' ELSE '' END + 
CASE WHEN @showcashier = 1 THEN ',[Cashier] VARCHAR(100)' ELSE '' END + 
CASE WHEN @showregister = 1 THEN ',[Register] VARCHAR(20)' ELSE '' END, 2, 2000);

DECLARE myCursor CURSOR FOR
    SELECT DISTINCT c.CurrencyDesc 
    FROM dbo.Currencies AS c INNER JOIN dbo.rpPay AS p ON c.POSCurrency = p.PayType 
        INNER JOIN dbo.RPTrs AS r ON r.ReceiptNO = p.ReceiptNo
    WHERE
        c.CurrencyDesc <> 'Testing' AND c.CurrencyDesc <> 'Cash Change' AND
        r.TRSDate >= @startdate AND r.TRSDate <= @enddate
OPEN myCursor
FETCH NEXT FROM myCursor INTO @result0
WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @sql = @sql + ',[' + @result0 + '] INT'
        FETCH NEXT FROM myCursor INTO @result0
    END
CLOSE myCursor
DEALLOCATE myCursor

SET @sql = @sql + ')'
EXECUTE sp_executesql @sql, N'@startdate DATETIME, 
    @enddate DATETIME',@startdate, @enddate;

SET @sql = 'SELECT * FROM ##a13; DROP TABLE ##a13'
EXECUTE sp_executesql @sql

行のないテーブルを返します。(Currencies テーブルには、ここに示されているよりも多くの CurrencyDesc があることに注意してください。これらは、提供された日付範囲で使用されているものに過ぎないためです)

ここに画像の説明を入力

これはまさに私が期待するものです。これまでのところ素晴らしい。ここで、日付範囲 ( ) に基づいてデータの行を追加する必要があり@startdate >= and <= @enddate、4 つの可能なオプションからチェックした内容に応じて ( @showstore, @showcashier, @showdate, @showregister)

例: 2013 年 1 月 1 日から 2013 年 2 月 28 日までの日付で、登録のみを表示する (図に示されているように) には、次の DATA が必要です。

  | Register | Cash  | House Acct | MasterCard | Visa/MC
--------------------------------------------------------
1 | 01       | 20.00 | 235.25     | 1235.32    | 135.23
2 | 02       | 30.00 | 3542.42    | 323.52     | 523.64
3 | 03       | 23.35 | 100.32     | 3267.24    | 235.25

2005/2008 の理由は、これが実行されるクライアントの一部がまだ 2005 を使用しているためです。使用するPIVOTには、2005 である各データベースの互換性レベルを変更する必要があります。

PS。再び怒鳴られる前に、グローバルな ##a13 の代わりに #a13 を使用すると、

Msg 208, Level 16, State 0, Line 1
Invalid object name '#a13'.

グローバル一時テーブルを使用しないようにするにはどうすればよいですか?

4

1 に答える 1

6

ここで間違っている場合は、明確にしてください。

ユーザー入力に基づいてテーブルに動的列を設定する方法を尋ねていると思います。ここでの正しい答えは、それをしないでください!

この種のベスト プラクティスは、出力テーブルにすべてのフィールドを配置し、アプリケーション/ディスプレイ レイヤーで、ユーザーが要求したフィールドのみを表示することです。

見栄えを良くするためだけに TSQL 内のテーブル レイアウトをカスタマイズすると、多くの不必要な複雑さが生じます。この複雑さには、パフォーマンス コストの増加も伴います。

静的な出力テーブルがある場合、指定されたパラメーターを使用してデータを返すのは簡単です。

于 2013-02-28T19:52:06.367 に答える