none
Abfrage für den CSV-Export RRS feed

  • 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

    Samstag, 6. August 2011 18:37

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
    




    Samstag, 6. August 2011 21:41

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
    Samstag, 6. August 2011 19:04
    Moderator
  • 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
    




    Samstag, 6. August 2011 21:41
  • 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. 

    Sonntag, 7. August 2011 12:58
  • Hi,
     
    möchtest Du die Daten im XML-Format online über ein Webservice zur Verfügung stellen oder werden die Daten in einem regelmäßigen Abstand exportiert und als eine XML-Datei zum Download angeboten?
     
    Im zweiten Fall könnte man SSIS einsetzen.
    Sonntag, 7. August 2011 13:50
  • 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
    Sonntag, 7. August 2011 14:30
    Moderator
  • 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 zum
    Teufel 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 extra
    CSV-für Kundendaten und die Verknüpfung über eine KundenID.
    Vielleicht hilft es ja auch die CSV noch zu packen.
     
    Lutz
     
    Montag, 8. August 2011 12:58