2009-06-10 13 views
0

Ich mag es nicht, das gleiche an zwei Stellen definiert zu haben, wenn ich es vermeiden kann.Refaktorierte SQL-Projektion?

Ich erkenne, dass die zwei Abfragen unten mit zwei verschiedenen Tabellen beschäftigen, aber diese Tabellen enthalten im Grunde die gleiche Art von Daten (verschiedene Prädikate rechtfertigen die beiden Abfragen), und ich denke an die beiden Projektionen unten als "das Gleiche definiert an zwei Stellen ".

Wann/wenn ich später diese Abfragen ändern, verschiedene Spalten enthalten, ich bin sicher, dass ich immer werde die Projektionen bleiben identisch wollen.

Daran, und ohne Verwendung von dynamischem SQL, und ohne '*' in einer beliebigen Projektion (in meiner Produktionsumgebung nicht zulässig), kann ich den "columnset" einmal definieren und in beiden Abfragen verwenden?

SELECT columnA 
    , columnB 
    , columnC 
FROM Data 

SELECT columnA 
    , columnB 
    , columnC 
FROM DataArchive 
+0

Sie haben Daten an zwei Stellen gespeichert. Egal, um die Daten, die Sie für einen bestimmten Anruf benötigen, abzurufen, müssen Sie wissen, aus welchem ​​Datenbestand sie abgerufen werden. Die veröffentlichten SELECT ... UNION ALL ... -Lösungen würden nur eine Abfrage benötigen, aber Sie müssten den "Schalter" hinzufügen, um zu steuern, welcher Satz tatsächlich abgefragt wurde. Können Sie das zu Ihrer Codebasis hinzufügen? Ich bevorzuge Blixt's View-Implementierung, aber ich würde auch vorschlagen, die Tabellen in einer Tabelle zu kombinieren. (Es klingt wie eine "aktuelle/kleine/häufig verwendete Menge vs. historische/ginormous/selten verwendete Set" -Situation, aber Sie können nie wissen.) –

Antwort

1

Haben Sie Ihre Basis eine Vereinigung von Daten und DataArchive sein und eine Inline-Tabellenwertfunktion (SQL Server 2005 und höher) verwenden?

CREATE FUNCTION UnifiedData (@LiveOnly bit, @ArchiveOnly bit) 
RETURNS TABLE 
AS 
RETURN (
    SELECT columnA 
      ,columnB 
      ,columnC 
    FROM (
     SELECT 'Live' AS Src, * 
     FROM Data 
     WHERE @ArchiveOnly = 0 

     UNION ALL 

     SELECT 'Archive' AS Src, * 
     FROM DataArchive 
     WHERE @LiveOnly = 0 
    ) 
) 

Nicht groß, aber sollte ziemlich gut vom Optimierungsprogramm behandelt werden, da es inlined ist.

+0

Ich mag es. Ich habe jetzt der Frage das '*' Verbot hinzugefügt. Ich entschuldige mich dafür, dass ich es ursprünglich nicht aufgenommen habe. – lance

+0

Das * hier ist relativ harmlos, da es intern und nicht belichtet ist. Es sollte auch immun gegen Änderungen in Daten und Datenarchiv sein, die dazu führen könnten, dass es bricht, wenn sie nicht aufhören, das gleiche Schema zu haben. Normalerweise befürworte ich seine Verwendung nur, wenn dies gerechtfertigt ist. –

+0

Kleine Quatsch, aber wäre UNION ALL besser geeignet? –

0

Ich kann nicht an eine effiziente Möglichkeit denken. Man könnte natürlich eine Ansicht mit einem UNION ALL der beiden Tabellen mit der Zugabe einer Spalte machen, die die Tabellennamen als String hält, dann SELECT columnA, columnB, columnC FROM view WHERE table = 'Data' tun, aber das fühlt sich an wie eine ziemlich hässliche Hack.

0

Ja, ist SQL so schrecklich. Es gibt keinen rundum zufriedenstellenden Weg, dies zu tun. Hier ein Beispiel mit Synonymen:

if object_id('DataSynonym') is not null drop synonym DataSynonym 
create synonym DataSynonym for Data 
select columnA, columnB, columnC from DataSynonym 

if object_id('DataSynonym') is not null drop synonym DataSynonym 
create synonym DataSynonym for DataArchive 
select columnA, columnB, columnC from DataSynonym 

Das Problem mit der Verwendung von Synonymen auf diese Weise ist, dass sie global im Umfang sind. Wenn Sie ein Synonym spontan in einer Verbindung neu definieren, wirkt sich dies auf alle anderen Verbindungen aus.

Temporäre Ansichten/Funktionen oder Ansicht/Funktionsvariablen würde einen langen Weg, um das Problem zu beheben. Oder eine Makrosprache, wie sie in SAS verfügbar ist.

0

Erstellen Sie eine Ansicht auf die Daten UNION ALL DataArchive. Wenn Sie später die 2 Tabellen umstrukturieren und kombinieren können, ist dies für Ihre vorhandenen Abfragen transparent.