2017-04-26 4 views
0

Ich bin nicht sicher, was der beste Titel meiner Frage wäre, aber ich werde mein Problem/Frage der beste unten erklären:SQL - Für jede Schleife in einer Abfrage

ich die folgende Abfrage verwenden , wo ich auf einem Arbeitsauftrag filtern, und ich sammle alle die Geschichte davon, die ich gezeigt zu meinem Bericht benötigen würde:

select a.name, d.data, h.started, e.name, * from wshhistory h 
join asset a 
on a.uid = h.assetid 
join wshfld d 
on h.uid = d.wshhistid 
join fielddefinition f 
on d.flddefid = f.uid 
join enumlookup e 
on h.assetstatus = e.uid 
where h.shdid = '43FEB092-D3B1-4008-9C44-A3A249987849' order by a.name, h.started asc 

Mein Ergebnis ist in Ordnung, aber ...

enter image description here

Was? Ich würde nur 1 Zeile (die letzte/oberste) von jedem (einzigartigen) Asset und die anderen Zeilen alle als Spalte benötigen, so dass wir nur 1 Zeile für jedes Asset haben. So, dass mein Bericht wie folgt aussieht:

enter image description here

In vb.net würde ich mit einem Fix diese für jede Schleife alle Vermögenswerte gehen durch, aber mit SQL mein Wissen ist begrenzt, und ich habe keine Ahnung, wie man das in einer Abfrage löst.

Irgendeine Idee?

Vielen Dank im Voraus!

+0

Mögliche Duplikat arbeiten [Select erste Zeile in jeder Gruppe GROUP BY?] (http://stackoverflow.com/questions/3800551/select-first-row-in-each-group-by-group) –

+0

Wenn ich nach Name (oder Asset-ID) gruppieren würde , dann bekomme ich die Nachricht: Die Spalte 'asset.name' ist in der Auswahlliste ungültig, weil sie nicht in einem Aggregat f enthalten ist oder die GROUP BY-Klausel. Wenn ich alle diese Auswahlkriterien entfernen und mit * gehen würde, bekomme ich immer noch die gleiche Fehlermeldung, aber mit einer anderen Spalte ('wshhistory.uid') – GertDeWilde

+1

Wenn Sie gruppieren müssen Sie nach allen Spalten gruppieren, die nicht sind aggregiert. Und Sie sollten die Verwendung von select * auf jeden Fall vermeiden. Benennen Sie die Spalten explizit. –

Antwort

2

Um die von Ihnen angegebene Ausgabe zu erstellen, können Sie eine bedingte Aggregation verwenden. Etwas wie das.

select a.name 
    , min(case when d.data = 'Pre Use' then d.data end) as PreUse 
    , min(case when d.data = 'Connected' then d.data end) as Connected 
    , min(case when d.data = 'Let Go' then d.data end) as LetGo 
    , min(case when d.data = 'Disconnected' then d.data end) as Disconnected 
from wshhistory h 
join asset a on a.uid = h.assetid 
join wshfld d on h.uid = d.wshhistid 
join fielddefinition f on d.flddefid = f.uid 
join enumlookup e on h.assetstatus = e.uid 
where h.shdid = '43FEB092-D3B1-4008-9C44-A3A249987849' 
group by a.name 
order by a.name 
+0

Dies funktioniert für seinen Mock bis zu den Ergebnissen, die er will, aber es funktioniert nicht mit dem Select all (*) in seiner Abfrage. Ich verwende gerne Windows-Funktionen für diese (z. B. row_number), so dass Sie alle Spalten für den ersten Datensatz zurückholen können. – KeithL

+0

@KeithL Ich stimme zu, aber in den gewünschten Ergebnissen ist es ziemlich klar, dass sie nicht jede Spalte benötigen. –

+0

Das * war für einige zusätzliche Informationen, aber nicht für das, was ich auf dem Bericht wollte. Das ist also was ich will/brauche. Entschuldigung für die Verwirrung. Vielen Dank, du willst nicht wissen, wie viel Zeit ich dafür genommen habe und wie viel Zeit du mir gerade gespart hast! :) – GertDeWilde

0

Versuchen Sie, eine Dreh:

WITH A AS(
SELECT a.name , d.data , h.started 
FROM wshhistory h 
    join asset a 
    on a.uid = h.assetid 
    join wshfld d 
    on h.uid = d.wshhistid 
    join fielddefinition f 
    on d.flddefid = f.uid 
    join enumlookup e 
    on h.assetstatus = e.uid 

WHERE h.shdid = '43FEB092-D3B1-4008-9C44-A3A249987849' 
) 
SELECT * FROM a 

PIVOT(MAX(startdate) FOR data IN ([Pre Use],[Connected],[Let Go],[Disconnected])) AS MaxStarted 

Da Sie nicht einige Daten erstellt haben, für uns kann ich es nicht testen, aber es sollte wohl :)