Frage

Ich frage mich, wie andere mit dieser Situation umgehen ... und wie das anwenden Sie Repeat Yourself nicht (DRY) Prinzip auf diese Situation.

Ich finde ich ständig Verschwenkung oder Schreiben von CASE-Anweisungen in T-SQL Monate als Spalt zu präsentieren. Ich habe in der Regel einige Felder, die (1) ein Datumsfeld enthalten werden, und (2) ein Wertfeld. Als ich diese wieder zu einem Benutzer über eine ASPX Seite präsentieren oder Reporting Services Ich brauche die letzten am weitesten rechts stehenden 14 Spalten haben, um diese Muster zu haben:

[Jahr], [Jan], [Februar], [Mar], [April], [Mai], [Juni], [Juli], [August], [September], [Oct], [November] [Dezember], [Total]

Wo Jahr ist das Jahr als int und jedes zweite Feld ist das Wertefeld für diesen Monat summiert (mit Ausnahme von [Total], die den Gesamtwert Feld für das Jahr).

Ich mag einen wiederverwendbaren Weg finden, diese zu handhaben. Offen für alle Vorschläge (T-SQL / ANSI SQL)

War es hilfreich?

Lösung

Dies ist nicht genau das, was Sie suchen, aber ich habe eine Menge von sich wiederholenden UNPIVOT getan, und in der Regel würde ich Code-gen diese, mit irgendeiner Art von standardisierten Benennung und verwenden CTEs stark:

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

Sie können so etwas wie dieser CODEGEN durch eine Tabelle oder eine Sichtprüfung und mit:

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

Und templatizing den Code:

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)

etc.

Natürlich ist es möglich, diesen Code dynamisch oder erstellen und SP laufen und Sie können eine Ansicht auslagern oder Tabelle erstellt vorübergehend nur Metadaten für etwas Inline aufzunehmen.

Siehe Anmerkungen zu Tabellenwertfunktionen und OUTER Technik anwenden.

Andere Tipps

Es ist spät und ich könnte etwas offensichtlich hier fehlt, wird aber eine Monate Tabelle mit einer Zeile für jeden Monat Hilfe Sie das tun?

/* 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.
  */

Wie wäre es eine Ansicht mit?

Wenn Sie immer für die gleiche Tabelle / Gruppe von Tabellen gehen, könnte ein Blick Sinn machen. CAVEAT. Hüten Sie sich vor solchen Ansichten, wenn kleine Abschnitte von großen Tabellen mit .. der Ansicht könnte das Optimierungsprogramm verhindern, tun es die Aufgabe

Wie @Justice in den Kommentaren erwähnt, bezieht sich allgemein auf DRY wieder verwendbaren Code, die in Ihrer viel einfacher ist, die Sprache des SQL-Client nicht in der SQL. Wenn Sie auf diese Option offen sind (und zwar, können Sie nicht), sollten Sie eine DataMapper wie Mybatis . Die Extraktion in Objekte können Overkill für das, was Ihr nach, aber die Fähigkeit, SQL-Schnipsel zu erstellen und sie in verschiedenen Abfragen Wiederverwendung klingt wie, was Sie nach.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top