Zusammenführen mehrerer Zeilen auf Basis eines eindeutigen Bezeichners in SQL server (GROUP_CONCAT für SQL server)?

Ich habe anfangs versucht, dies über PHP herauszufinden, aber ich habe nicht viel Glück …

Wie kann ich alle Duplikate im Array auf Basis eines Key-Wertes zusammenführen?

Da ich keine Lösung gefunden habe, habe ich beschlossen, mein Problem über meine SQL-Abfrage zu lösen. Was muss ich wissen, wie kann ich die Unterschiede zwischen den zurückgegebenen Zeilen in dieser Abfrage "zusammenführen"?

SELECT Item.ID, Item.ItemLookupCode, nitroasl_pamtable.ManufacturerPartNumber, SupplierList.ReorderNumber, Item.Notes, Item.Description, Item.ExtendedDescription, Item.Quantity, nitroasl_pamtable.SpoofStock, Item.Price, nitroasl_pamtable.PAM_Keywords FROM Item JOIN nitroasl_pamtable ON Item.ID = nitroasl_pamtable.ItemID JOIN SupplierList ON Item.ID = SupplierList.ItemID WHERE (Item.ItemLookupCode LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (nitroasl_pamtable.ManufacturerPartNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (SupplierList.ReorderNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.Notes LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.Description LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.ExtendedDescription LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (nitroasl_pamtable.PAM_Keywords LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) ORDER BY Item.ItemLookupCode ASC; 

Was ich denke, ich brauche (habe aber nicht erfolgreich umgesetzt)

MySQL's GROUP_CONCAT entspricht

Ich glaube, diese function würde tun, was ich brauche, aber ich verwende SQL server – nicht MySQL. Und ich kann nicht scheinen, die gebuchten Lösungen zu bekommen, wie man das macht, um für mich zu arbeiten …

Was ich versucht habe:

In letzter time habe ich versucht, die MAX() und die GROUP BY function (zusammen), aber es wählt den MAX Wert, der in den doppelten Zeilen zurückgegeben wird, so dass eine einzelne Zeile mit den MAX Werten in jeder Spalte zurückgegeben wird.

 SELECT MAX(Item.ID) AS Id, Item.ItemLookupCode, MAX(nitroasl_pamtable.ManufacturerPartNumber) AS ManufacturerPartNumber, MAX(SupplierList.ReorderNumber) AS ReorderNumber, MAX( CAST(Item.Notes AS varchar(max)) ) AS Notes, MAX(Item.Description) AS Description, MAX( CAST(Item.ExtendedDescription AS varchar(max)) ) AS ExtendedDescription, MAX(Item.Quantity) AS Quantity, MAX(nitroasl_pamtable.SpoofStock) AS SpoofStock, MAX(Item.Price) AS Price, MAX(nitroasl_pamtable.PAM_Keywords) AS PAM_Keywords, MAX(Item.PictureName) AS PictureName FROM Item LEFT JOIN nitroasl_pamtable ON Item.ID = nitroasl_pamtable.ItemID LEFT JOIN SupplierList ON Item.ID = SupplierList.ItemID WHERE (Item.ItemLookupCode LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (nitroasl_pamtable.ManufacturerPartNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (SupplierList.ReorderNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.Notes LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.Description LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.ExtendedDescription LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (nitroasl_pamtable.PAM_Keywords LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) GROUP BY Item.ItemLookupCode ORDER BY Item.ItemLookupCode ASC 

Anstatt die Varianten jeder Spalte zu vercasting, würde ich gern alle zurückgegebenen Werte jeder Spalte (die mit MAX verworfen werden) in ihre jeweiligen / original Spalten, die durch ein Komma …

Was ich brauche:

databaseschema (Beispiel)

In der obigen file sehen Sie die vier Zeilen, die von der obigen SQL-Abfrage zurückgegeben werden. Ich möchte eine Zeile zurückgeben, die so aussieht:

ICH WÜRDE:

 8265 

ItemLookupCode:

 TP-AC1750 

HerstellerPartennummer:

 Archer C7 

ReorderNumber:

 7681617, ARCHERC7, N82E16833704177 

Notizen:

 TP-LINK Archer C7 AC1750 Routr 

Beschreibung:

 TP-LINK Archer C7 AC1750 Routr 

ExtendedDescription:

 TP-Link Archer C7 Wireless-AC1750 Dual-Band Gigabit Router 

Anzahl:

 0 (This should actually be a combined sum/total of the values in this column) 

SpoofStock:

 NULL (Same as Quantity - Should be sum / This value is different than Quantity) 

Preis:

 129.95 

PAM_Keywords:

 NULL 

Ich weiß, es gibt einen besseren path, um diese Abfrage zu schreiben. Ich bin einfach kein SQL-Typ. Diese Abfrage / Skript ist eine Keyword-search, die Elemente in unserer Microsoft Dynamics RMS-database zurückgibt und JSON ausgibt, die ich verwende, um eine list von Produkten zu erstellen, die geändert und erneut in die DB übertragen werden können. Ich benutze SQL server 2008 R2 (wenn das wichtig ist). Irgendwelche Ratschläge, wie ich die oben genannte Ausgabe unter Verwendung einer Variation meiner Abfrage erreichen kann, wäre sehr dankbar! Vielen Dank

Update (SQLFiddle)

Hier ist ein Link zu einem SQLFiddle zu spielen mit 🙂

SQLFiddle mit keine MAX-function

SQLFiddle mit MAX-function (keine lebensfähige Lösung, da ich data verliere)

Solutions Collecting From Web of "Zusammenführen mehrerer Zeilen auf Basis eines eindeutigen Bezeichners in SQL server (GROUP_CONCAT für SQL server)?"

Dies wird Ihnen begonnen, aber es gibt noch einige Ungewissheit um die nitroasl_pamtable Tabelle, also habe ich das nicht eingeschlossen.

 SELECT I.ID, I.ItemLookupCode, I.Notes, I.Description, I.ExtendedDescription, I.Quantity, I.Price, SL.ReorderNumbers, P.SpoofStock, P.ManufacturerPartNumber, P.PAM_Keywords FROM Item I LEFT JOIN nitroasl_pamtable P ON I.ID = P.ItemID OUTER APPLY ( SELECT ReorderNumbers = Substring(( SELECT DISTINCT Convert(varchar(max), ', ' + SL.ReorderNumber) FROM SupplierList SL WHERE I.ID = SL.ItemID FOR XML PATH(''), TYPE ).value('.[1]', 'varchar(max)'), 3, 2147483647) ) SL WHERE I.Price > 0.00 AND I.WebItem = 1 AND ( I.ItemLookupCode LIKE '%tp-ac1750%' OR I.Notes LIKE '%tp-ac1750%' OR I.Description LIKE '%tp-ac1750%' OR I.ExtendedDescription LIKE '%tp-ac1750%' OR P.ManufacturerPartNumber LIKE '%tp-ac1750%' OR P.PAM_Keywords LIKE '%tp-ac1750%' OR EXISTS ( SELECT * FROM dbo.SupplierList SL2 WHERE I.ID = SL2.ItemID AND SL2.ReorderNumber LIKE '%tp-ac1750%' ) ) ORDER BY I.ItemLookupCode ASC; 

Um nitroasl_pamtable korrekt zu bringen, für jede Spalte, die du verketten willst, könntest du einen neuen OUTER APPLY . Sie können eine einzige OUTER APPLY , um sofort alle Spalten, die normale Aggregation (wie Sum() ).

Allerdings möchte ich anbieten, dass diese Verkettung die data in einer Weise verdecken wird, die zu einer errorshaften Beurteilung oder Entscheidungen führen könnte. Wenn man 3 Werte aus einer Tabelle zieht und sie verkettt / summiert, wird sie eine einzelne Einheit erscheinen lassen, die möglicherweise nicht korrekt ist.

Eine andere Art und Weise, dass die Verkettung schädlich sein kann, ist mit den Nachbestellungsnummern. Beachten Sie, dass ich einen DISTINCT da drüben wegen der zwei doppelten Nachbestellungsnummern – aber sie waren von verschiedenen Lieferanten. Also, was gut ist eine Nachbestellungsnummer abgesehen vom Lieferanten, aus dem es stammen kann? Was, wenn zwei verschiedene Artikel die gleiche Nachbestellnummer bei verschiedenen Lieferanten haben? ( BIGBOX B. Neuordnung Nummer BIGBOX ist ein Fernseher bei einem Lieferanten, aber es ist ein riesiger Karton an der anderen.)

Ich bin nicht davon überzeugt, dass es eine gute Idee ist, diese Werte in der Abfrage zu verketten. Stattdessen sollte die Benutzeroberfläche die Abfragen separat (die Items als ein Rowset, dann die unterstützenden data von jeder anderen Tabelle als einzelne rowsets) und dann präsentieren die data in einer Weise, die Sinn macht in der Benutzeroberfläche.

Wenn ich das richtig verstehe, sieht es so aus, als ReorderNumber du nur das Feld " ReorderNumber verketten. Sie könnten ein SQLCLR User-Defined Aggregate (UDA) verwenden, um dies einfach zu tun.

Es gibt eine vorgefertigte UDA, um dies zu tun namens Agg_Join in der SQL # -Bibliothek von SQLCLR-functionen, gespeicherte Prozeduren, etc (das bin ich der Autor von, aber diese aggregierte function ist in der Free-Version verfügbar). Mit ihm würde es Ihre Abfrage wie folgt aussehen:

 SELECT MAX(Item.ID) AS Id, Item.ItemLookupCode, MAX(nitroasl_pamtable.ManufacturerPartNumber) AS ManufacturerPartNumber, SQL#.Agg_Join(SupplierList.ReorderNumber) AS ReorderNumber, MAX( CAST(Item.Notes AS varchar(max)) ) AS Notes, MAX(Item.Description) AS Description, MAX( CAST(Item.ExtendedDescription AS varchar(max)) ) AS ExtendedDescription, MAX(Item.Quantity) AS Quantity, MAX(nitroasl_pamtable.SpoofStock) AS SpoofStock, MAX(Item.Price) AS Price, MAX(nitroasl_pamtable.PAM_Keywords) AS PAM_Keywords, MAX(Item.PictureName) AS PictureName FROM Item LEFT JOIN nitroasl_pamtable ON Item.ID = nitroasl_pamtable.ItemID LEFT JOIN SupplierList ON Item.ID = SupplierList.ItemID WHERE (Item.ItemLookupCode LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (nitroasl_pamtable.ManufacturerPartNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (SupplierList.ReorderNumber LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.Notes LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.Description LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (Item.ExtendedDescription LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) OR (nitroasl_pamtable.PAM_Keywords LIKE '%tp-ac1750%' AND Price > 0.00 AND WebItem = 1) GROUP BY Item.ItemLookupCode ORDER BY Item.ItemLookupCode ASC; 

Gerade zu erwähnen, enthält die Vollversion von SQL # eine funktionellere Version von Agg_Join namens Agg_JoinPlus , die das Sortieren erlaubt, das Herausfiltern von Duplikaten, das Ersetzen von NULLs , das Ändern des Trennzeichens usw.

Oder wenn du das auf eigene Faust erstellen möchtest, in welchem ​​Fall du die functionalität anpassen kannst, habe ich einen Artikel geschrieben, der ein Beispiel für die Erstellung eines benutzerdefinierten Aggregats zeigt, das einfach nur ein wenig geändert werden muss, um String-Verkettung zu machen: Getting Das Beste aus SQL server 2005 UDTs und UDAs (kostenlose Registrierung erforderlich). Das wurde geschrieben, bevor SQL server 2008 herauskam, dass die Möglichkeit hatte, MaxSize auf -1 zu setzen, so dass es mehr als 8000 Bytes zu einem timepunkt speichern kann (was eher ein Problem für diese Art von Operation ist, als es für viele Arithmetik ist Operationen).

Eine weitere Option, die keine Abonnements erfordert und aus der Box herausarbeiten sollte (ich habe es selbst nicht ausprobiert) ist dieses Open-Source-Projekt:

GROUP_CONCAT String Aggregate für SQL server

Dieses Projekt wurde nicht aktualisiert seit 2013-05-09, aber ich vermute, dass es tun würde, was Sie wollen und würde in Ihre Abfrage passen wie SQL # .Agg_Join und jede andere Aggregat. Es gibt ein Installations-Skript, GroupConcatInstallation.sql , im Ordner " Installation Scripts ", der die Assembly- und T-SQL-Wrapperobjekte enthält.

Und ja, alle diese Aggregate sollten mit PHP oder etwas anderes arbeiten, da sie Teil der Abfrage sind und daher ist es SQL server, die die Verarbeitung und es hat nichts mit einer bestimmten Client-Software zu tun.