Benutzer mit den meisten Antworten
Abfrage für den CSV-Export

Frage
-
Hallo,
ich muss die Daten von drei Tabellen exportieren als CSV. Ist nun eigentlich kein Problem, handelt es sich hier um eine n:m-Beziehung. Ein Kunde kann zum beispiel mehrere Bestellungen haben. Würde so aussehen.
Kunde A, Bestellung 1, Produkt 1 Kunde A, Bestellung 1, Produkt 2 Kunde A, Bestellung 1, Produkt 3 Kunde B, Bestellung 2, Produkt 1 ...
Nun sind hier redundante Daten enthalten. Die Daten zum Kunden und generell zur Bestellung wiederholen sich immer wieder. Da ich das CSV online zum Download anbieten möchte, sollte es relativ schlank bleiben. Ich dachte mir, dass man es auch folgendermaßen exportieren könnte:Kunde A, Bestellung 1, Produkt 1 , , Produkt 2 , , Produkt 3 Kunde B, Bestellung 2, Produkt 1 ...
Nur eben ohne die Leerzeichen, nur zur Visualisierung hier. Das heißt meine Abfrage müsste für die leeren Felder, anstelle der redundanten Daten null zurückliefern. Wie konstruiert man aber eine solche SQL-Abfrage?Vielen Dank für eure Hilfe
Antworten
-
Hallo,ich stimme Stefan zu, aber hier ist ein Lösungsvorschlag von mir:
use tempdb go create table Kunde ( KundeID int identity, Name nvarchar(55) ) go create table Bestellung ( BestellungName nvarchar(55), KundeID int, ProduktID int ) go create table Produkt ( ProduktID int identity, Name nvarchar(55) ) go insert into Kunde values ('Kunde1'), ('Kunde2') go insert into Produkt values ('Produkt1'), ('Produkt2'), ('Produkt3') go insert into Bestellung values ('Bestellung 1',1,1),('Bestellung 1',1,2),('Bestellung 1',1,3), ('Bestellung 2',2,1),('Bestellung 2',2,2),('Bestellung 2',2,3) go ;with t1 as ( select k.Name KundeName, b.BestellungName, p.Name as ProduktName ,rank() over ( partition by k.Name, b.BestellungName order by k.Name,b.BestellungName,p.Name ) as [rank] from Kunde k inner join Bestellung b on k.KundeID = b.KundeID inner join Produkt p on b.ProduktID = p.ProduktID ) select (case [rank] when 1 then KundeName else null end) as KundeName, (case [rank] when 1 then BestellungName else null end) as BestellungName, ProduktName from t1 go drop table Kunde, Bestellung, Produkt go
- Als Antwort vorgeschlagen Falk Krahl Montag, 8. August 2011 12:12
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 16. August 2011 11:15
Alle Antworten
-
Hi,
eine CSV Datei mit dem gewünschten Aufbau macht nicht wirklich Sinn, es sei denn, diese wird über eine manuelle Steuerung verarbeitet.
Ich persönlich würde, wenn mir daran gelegen ist, die Datenmenge möglichst klein zu halten, separate CSV Dateien (Kunde, Bestellung, Produkte je Bestellung) anbieten.
Per einfachem SELECT Statement wirst Du die gewünschte Ausgabe nur schwerlich umsetzen können. Es wäre daher sinnvoller, das in der Methode, die den CSV Inhalt erstellt, zu machen. Hierfür selektierst Du wie gehabt, sortierst dabei nach Kundennummer und darin nach Bestellnummer. Jetzt kannst Du einfach einen StringBuilder aufbauen, mit dem Du den gewünschten Inhalt zusammenstellen kannst. (Schleife über alle Datensätze, merken der Kunden- und der Bestellnummer. Ausgabe der Werte nur, wenn sich die Kunden- und/oder Bestellnummer geändert haben)
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Hallo,ich stimme Stefan zu, aber hier ist ein Lösungsvorschlag von mir:
use tempdb go create table Kunde ( KundeID int identity, Name nvarchar(55) ) go create table Bestellung ( BestellungName nvarchar(55), KundeID int, ProduktID int ) go create table Produkt ( ProduktID int identity, Name nvarchar(55) ) go insert into Kunde values ('Kunde1'), ('Kunde2') go insert into Produkt values ('Produkt1'), ('Produkt2'), ('Produkt3') go insert into Bestellung values ('Bestellung 1',1,1),('Bestellung 1',1,2),('Bestellung 1',1,3), ('Bestellung 2',2,1),('Bestellung 2',2,2),('Bestellung 2',2,3) go ;with t1 as ( select k.Name KundeName, b.BestellungName, p.Name as ProduktName ,rank() over ( partition by k.Name, b.BestellungName order by k.Name,b.BestellungName,p.Name ) as [rank] from Kunde k inner join Bestellung b on k.KundeID = b.KundeID inner join Produkt p on b.ProduktID = p.ProduktID ) select (case [rank] when 1 then KundeName else null end) as KundeName, (case [rank] when 1 then BestellungName else null end) as BestellungName, ProduktName from t1 go drop table Kunde, Bestellung, Produkt go
- Als Antwort vorgeschlagen Falk Krahl Montag, 8. August 2011 12:12
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 16. August 2011 11:15
-
Danke für eure Antworten, ich denke, dass in meinem Fall CSV nicht das richtige Format ist. XML wird meine Daten besser abbilden könnte. Mal sehen, ob ich ein solches XML direkt so vom Server zurückgeben kann. Wenn nicht, dann werde ich es über XML-Serialisierung machen.
-
-
Danke für eure Antworten, ich denke, dass in meinem Fall CSV nicht das richtige Format ist. XML wird meine Daten besser abbilden könnte. Mal sehen, ob ich ein solches XML direkt so vom Server zurückgeben kann. Wenn nicht, dann werde ich es über XML-Serialisierung machen.
Hi,
für XML kannst Du bspw. in .NET problemlos entsprechende Klassen aufbauen und diese dann per Serialisierung als XML erzeugen lassen.
Ausgehend vom "Hauptobjekt" (also ob Du primär von den Bestellungen oder von den Kundendatensätzen ausgehst) könnte eine solche Struktur als Liste der Bestellungen bspw. so aussehen:
Dim Bestellungen As List( Of Bestellung ) ... <Serizalizable()> _ Public Class Bestellung Public Kunde As Kunde Public Artikel As List( Of Artikel ) ... End Class <Serizalizable()> _ Public Class Kunde ... End Class <Serizalizable()> _ Public Class Artikel ... End Class
Natürlich sollten Properties mit Membervariablen, ... verwendet werden. Obiges dient nur als rudimentäres Beispiel.
Gruß, Stefan
Microsoft MVP - Visual Developer ASP/ASP.NET
http://www.asp-solutions.de/ - Consulting, Development
http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community -
Am 06.08.2011 20:37, schrieb Urbain de Puce:>> Nun sind hier redundante Daten enthalten. Die Daten zum Kunden und> generell zur Bestellung wiederholen sich immer wieder. Da ich das CSV> online zum Download anbieten möchte, sollte es relativ schlank bleiben.> Ich dachte mir, dass man es auch folgendermaßen exportieren könnte:>> Kunde A, Bestellung 1, Produkt 1> , , Produkt 2> , , Produkt 3> Kunde B, Bestellung 2, Produkt 1> ...>>> Nur eben ohne die Leerzeichen, nur zur Visualisierung hier. Das heißt> meine Abfrage müsste für die leeren Felder, anstelle der redundanten> Daten null zurückliefern. Wie konstruiert man aber eine solche SQL-Abfrage?Mach es bitte nicht!Jeder der irgendwann mal so eine CSV verarbeiten soll wird dich zumTeufel wünschen!!!Eine solche Datei läßt sich ohne zusätzliche Aufwand einbinden /importieren.Entweder so lassen und die doppelten Daten inkauf nehmen oder aber extraCSV-für Kundendaten und die Verknüpfung über eine KundenID.Vielleicht hilft es ja auch die CSV noch zu packen.Lutz