Frage

Ich habe eine SQL-Abfrage (MSSQLSERVER), wo ich Spalten der Ergebnismenge hinzufügen, mit Subselects:

SELECT P.name, 
(select count(*) from cars C where C.type = 'sports') AS sportscars,
(select count(*) from cars C where C.type = 'family') AS familycars,
(select count(*) from cars C where C.type = 'business') AS businesscars
FROM people P
WHERE P.id = 1;

Die Abfrage oben ist gerade von einem Testaufbau, der ein bisschen Unsinn ist, aber es dient auch genug, um als Beispiel denke ich. Die Abfrage ich eigentlich arbeiten umspannt eine Reihe von komplexen Tabellen, die in der Hand aus der Ausgabe ablenkt nur.

In dem obigen Beispiel jeder Datensatz in der Tabelle „People“ hat auch drei weitere Spalten: „wantsSportscar“, „wantsFamilycar“ und „wantsBusinesscar“. Nun, was ich tun möchte, ist nur die subselect jeden zusätzlichen Spalts tun, wenn die jeweiligen „will .....“ Feld in der Tabelle Personen ist auf „true“. Mit anderen Worten, ich möchte nur die erste subselect tun, wenn P.wantsSportscar für diese spezielle Person auf true gesetzt ist. Der zweite und dritte Subselects sollte in ähnlicher Weise arbeiten.

So ist die Art und Weise dieser Abfrage funktionieren soll, ist, dass es den Namen einer bestimmten Person zeigt und die Anzahl der Modelle für die Arten von Autos, die er besitzen will. Es könnte sein, bemerkenswert, dass meine letzte resultset immer nur einen einzelnen Datensatz enthält, nämlich die einen bestimmten Benutzer.

Es ist wichtig, dass, wenn eine Person in einer bestimmten Art von Autos ist nicht daran interessiert, dass die Spalte für diesen Typen nicht in der endgültigen Ergebnismenge aufgenommen werden. Ein Beispiel sicher sein ist klar:

Wenn Person A möchte ein Sportwagen und eine familycar, das Ergebnis würde die Spalten "Name", "Sportwagen" und "familycars" umfassen.

Wenn Person B eine businesscar will, wäre das Ergebnis die Spalten enthalten "name" und "businesscar".

Ich habe versucht, verschiedene Kombinationen mit IF, CASE zu verwenden und VORHANDEN Aussagen, aber bisher habe ich keine syntaktisch korrekte Lösung erhalten kann. Weiß jemand, ob dies überhaupt möglich ist? Beachten Sie, dass die Abfrage in einer gespeicherten Prozedur gespeichert werden.

War es hilfreich?

Lösung

In Ihrem Fall gibt es 8 Spalten-Layouts möglich und dies zu tun, werden Sie 8 separate Abfragen benötigen (oder bauen Sie Ihre Abfrage dynamisch).

Es ist nicht möglich, das Suchresultates Layout innerhalb einer einzigen Abfrage zu ändern.

Stattdessen können Sie Ihre Abfrage entwerfen wie folgt:

SELECT  P.name, 
        CASE WHEN wantssport = 1 THEN (select count(*) from cars C where C.type = 'sports') ELSE NULL END AS sportscars,
        CASE WHEN wantsfamily = 1 THEN (select count(*) from cars C where C.type = 'family') ELSE NULL END AS familycars,
        CASE WHEN wantsbusiness = 1 THEN (select count(*) from cars C where C.type = 'business') ELSE NULL END AS businesscars
FROM    people P
WHERE   P.id = 1

, welche NULL in entsprechenden Spalte wählen, wenn eine Person nicht will, und diese NULL der auf Client-Seite analysieren.

Beachten Sie, dass relationales Modell die Anfragen in Bezug auf relations beantwortet.

In Ihrem Fall ist die Beziehung wie folgt: „Diese Person Bedürfnisse sind satisifed mit so vielen Sportwagen, so viele Unternehmen Autos und so viele Familienautos“

Relationale Modell immer beantwortet diese spezifische Frage mit einer quartären Beziehung.

Es auslassen nicht eine der Beziehung Mitglieder: stattdessen setzt er sich nur NULL, die die Art und Weise des SQL ist es zu zeigen, dass das Mitglied einer Beziehung nicht definiert ist, anwendbar oder sinnvoll

.

Andere Tipps

Ich bin meistens ein Oracle-Typ, aber es gibt eine hohe Wahrscheinlichkeit, das gleiche gilt. Wenn ich nicht falsch verstanden haben, was Sie wollen, ist nicht möglich, auf dieser Ebene - Sie werden immer eine statische Anzahl von Spalten haben. Ihre Anfrage kann steuern, wenn die Spalte leer ist, aber da in dem äußersten Teil der Abfrage Sie X Anzahl der Spalten angegeben haben, werden Sie garantiert X-Spalten in Ihrer Ergebnismenge erhalten.

Wie gesagt, ich bin nicht vertraut mit MS SQL Server, aber ich vermute, es wird eine Möglichkeit der Ausführung dynamischen SQL, wobei in diesem Fall, dass die Forschung sollte, da es erlauben, sollten Sie eine flexiblere Abfrage zu erstellen.

Unter Umständen können Sie tun, was Sie wollen, indem Sie zuerst die Werte als separate Zeilen in eine temporäre Tabelle auswählen und dann auf die Tabelle ein PIVOT tun (die Zeilen in Spalten drehen).

  

Es ist wichtig, dass, wenn eine Person nicht   Interesse an einer bestimmten Art von Autos,   dass die Spalte für diese Art wird nicht   wird in der endgültigen Ergebnismenge enthält. Ein   Beispiel sicher sein ist klar:

Sie werden nicht in der Lage sein, es in einfachen SQL zu tun. Ich schlage vor, Sie gerade diese Spalte NULL machen oder NULL.

Wenn Sie die Abfrage soll dynamisch sein erweitern, wenn neue Autos hinzugefügt werden, dann sind Sie Verschwenkung könnte etwas helfen.

Es gibt drei Grundlagen Sie diese Arbeit einfach erlernen wollen zu machen. Die erste Datennormierung ist, die zweite ist GROUP BY, und die dritte ist verschwenken.

Als erste Datennormalisierung. Ihr Entwurf des Menschen Tabelle ist nicht in der ersten Normalform. Die Spalten „wantsports“, „wantfamily“, „wantbusiness“ sind wirklich eine sich wiederholende Gruppe, obwohl sie nicht so aussehen kann. Wenn Sie die Tabelle Design ändern können, werden Sie es vorteilhaft finden eine dritte Tabelle zu erstellen, nennen wir es „peoplewant“, mit zwei Schlüsselspalten, PersonID und Cartype. Ich kann ins Detail gehen, warum diese Konstruktion flexibler sein und mächtig, wenn Sie mögen, aber ich werde das überspringen für jetzt.

Auf zu GROUP BY. Dies ermöglicht es Ihnen, ein Ergebnis zu erzeugen, die jede Gruppe in einer Zeile des Ergebnisses zusammen.

SELECT 
    p.name, 
    c.type, 
    c.count(*) as carcount
FROM people p, 
   INNER JOIN peoplewant pw ON p.id = pw.personid 
   INNER JOIN cars c on pw.cartype = c.type
WHERE
   p.id = 1
GROUP BY 
   p.name,
   c.type

Diese (nicht getestet) Abfrage gibt Ihnen das gewünschte Ergebnis, mit der Ausnahme, dass das Ergebnis eine separate Zeile für jeden Fahrzeugtyp hat die Person will.

Schließlich verschwenken. Das PIVOT Werkzeug in Ihrem DBMS ermöglicht es Ihnen, dieses Ergebnis in eine Form zu drehen, wo es nur eine Zeile für die Person ist, und es gibt eine separate Spalte für jede der cartypes von dieser Person wollte. Ich habe nicht PIVOT selbst verwendet, so dass ich jemand anderen bearbeiten diese Antwort lassen ein Beispiel unter Verwendung von PIVOT bereitzustellen.

Wenn Sie die gleiche Technik, die Daten für mehrere Personen in einem Schwung zu holen, bedenken Sie, dass eine Spalte angezeigt wird für jeden Typ wollte, dass jede Person will, und Nullen werden für Personen im PIVOT Ergebnis erscheinen, die nicht wollen ein Fahrzeugtyp, die in den Ergebnisspalten ist.

kam in diesem Beitrag durch eine Google-Suche, so dass ich weiß, ich bin zu spät zu dieser Party ein wenig, aber .. sicher, dass dies wirklich ist möglich aber zu tun ..., Ich würde nicht wirklich es auf diese Weise tun vorschlagen, weil es in der Regel eine sehr schlechte Sache (tm).

betrachtet hat

Dynamische SQL ist Ihre Antwort.

Bevor ich sage, wie es zu tun, ich will das Vorwort mit Dynamic SQL ist eine sehr gefährliche Sache, wenn Sie nicht Ihre Eingabe von der Anwendung Desinfizieren.

So also mit Vorsicht vorgehen:

declare @sqlToExecute nvarchar(max);
declare @includeSportsCars bit;
declare @includeFamilyCars bit;
declare @includeBusinessCars bit;

set @includeBusinessCars = 1
set @includeFamilyCars = 1
set @includeSportsCars  = 1

set @sqlToExecute = 'SELECT P.name '

if @includeSportsCars = 1 
    set @sqlToExecute = @sqlToExecute + '(select count(*) from cars C where C.type = ''sports'') AS sportscars, ';
if @includeFamilyCars = 1
    set @sqlToExecute = @sqlToExecute + '(select count(*) from cars C where C.type = ''family'') AS familycars, ';
if @includeBusinessCars = 1
    set @sqlToExecute = @sqlToExecute + '(select count(*) from cars C where C.type = ''business'') AS businesscars '

set @sqlToExecute = @sqlToExecute + ' FROM people P WHERE P.id = 1;';

exec(@sqlToExecute)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top