Benutzer mit den meisten Antworten
SQL Abfrage für mehrfach vorkommende Werte in 2 Spalten

Frage
-
Auf Anregung eines Forenmitgliedes möchte ich hiermit einen neuen Thread für mein Problem eröffnen.
Mein Problem ist, alle Vorkommen von zwei verschiedenen Produktpaketen Pn in unterschiedlichen Filialen Fn zu zählen, genau dann wenn 2 Produktpakete in einer Filiale einmal als ProduktPaket1 und dann als ProduktPaket2 vorhanden sind. Das wird bei uns TWIN genannt.
Die nachfolgende Tabelle zeigt die Ausgangssituation:
Declare @myTab as Table(Filiale char(2), ProduktPaket1 char(2), ProduktPaket2 char(2));
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F1', 'P1', 'P2');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F1', 'P2', 'P1');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F2', 'P1', 'P2');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F1', 'P2', 'P1');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F2', 'P1', '');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F2', 'P1', 'P2');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F3', 'P3', 'P1');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F3', 'P1', '');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F3', 'P1', 'P3');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F3', 'P2', 'P1');
Insert into @myTab(Filiale, ProduktPaket1, ProduktPaket2)
values('F3', 'P1', 'P2');Das Ergebnis soll wie rechts gezeigt aussehen.
Ich habe mir schon die Zähne daran ausgebissen, aber bin zu keiner Lösung gekommen.
Vielleicht findet sich hier ja jemand, der mir auf die Sprünge helfen kann.
Im Voraus schon mal vielen Dank für evtl. Überlegungen.
Gruß Jürgen
Antworten
-
Den letzten Teil kann man natürlich auch noch etwas kürzen:
Select Twin, ProduktPaket1, ProduktPaket2, sum(case when Filiale = 'F1' then 1 else 0 end) as F1, sum(case when Filiale = 'F2' then 1 else 0 end) as F2, sum(case when Filiale = 'F3' then 1 else 0 end) as F3, count(distinct Filiale) as Anzahl_Filialen, count(*) as Anzahl_Kombi from cte group by Twin, ProduktPaket1, ProduktPaket2 order by Twin;
Einen schönen Tag noch,
Christoph
--
Microsoft SQL Server MVP
www.insidesql.org/blogs/cmu- Als Antwort markiert Jürgen Sch Freitag, 19. Oktober 2012 00:06
Alle Antworten
-
Hallo Jürgen,
ich würde es so machen:
SELECT 'P1_P2' AS Twin, COUNT(DISTINCT Filiale) AS AnzahlFilialen, COUNT(Filiale) AS AnzahlTwins FROM (SELECT Filiale, ProduktPaket1, ProduktPaket2 FROM test.dbo.tbl_Twins WHERE (ProduktPaket1 = N'P1') AND (ProduktPaket2 = N'P2') OR (ProduktPaket1 = N'P2') AND (ProduktPaket2 = N'P1')) AS Twin1 UNION ALL SELECT 'P1_P3' AS Twin, COUNT(DISTINCT Filiale) AS AnzahlFilialen, COUNT(Filiale) AS AnzahlTwins FROM (SELECT Filiale, ProduktPaket1, ProduktPaket2 FROM test.dbo.tbl_Twins WHERE (ProduktPaket1 = N'P1') AND (ProduktPaket2 = N'P3') OR (ProduktPaket1 = N'P3') AND (ProduktPaket2 = N'P1')) AS Twin2
-
Hallo Jürgen, versuch mal folgendes:
Select a.Filiale, case when a.ProduktPaket1 < a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end + '_' + case when a.ProduktPaket1 >= a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end as Twin, case when a.ProduktPaket1 < a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end as ProduktPaket1, case when a.ProduktPaket1 >= a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end as ProduktPaket2 from @myTab a where a.ProduktPaket1 is not null and a.ProduktPaket2 is not null and exists(Select * from @myTab b where a.ProduktPaket2 = b.ProduktPaket1 and a.Filiale = b.Filiale) order by Twin, Filiale; with cte as ( Select a.Filiale, case when a.ProduktPaket1 < a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end + '_' + case when a.ProduktPaket1 >= a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end as Twin, case when a.ProduktPaket1 < a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end as ProduktPaket1, case when a.ProduktPaket1 >= a.ProduktPaket2 then a.ProduktPaket1 else a.ProduktPaket2 end as ProduktPaket2 from @myTab a where a.ProduktPaket1 is not null and a.ProduktPaket2 is not null and exists(Select * from @myTab b where a.ProduktPaket2 = b.ProduktPaket1 and a.Filiale = b.Filiale) ) Select Twin, min(ProduktPaket1) as ProduktPaket1, min(ProduktPaket2) as ProduktPaket2, sum(case when Filiale = 'F1' then 1 else 0 end) as F1, sum(case when Filiale = 'F2' then 1 else 0 end) as F2, sum(case when Filiale = 'F3' then 1 else 0 end) as F3, count(distinct Filiale) as Anzahl_Filialen, count(*) as Anzahl_Kombi from cte group by Twin order by Twin;
Ich habe die Abfrage etwas gedreht, suche also (where exists...) nach den Sätzen, die als ProduktPaket1 das Element haben, was im äußeren Select in ProduktPaket2 ist.
Dadurch habe ich im äußeren Select immer beide ProduktPakete gefüllt und kann daraus den Twin zusammen bauen.
Dass bei einem Twin die Produktpakete aufsteigend sortiert werden sollen, habe ich mir mal aus der Grafik erschlossen, den sonst hätten wir ja nur zwei Twins bei Filiale 1 mit P2_P1 und der Satz mit P1_P2 würde unter den Tisch fallen.Einen schönen Tag noch,
Christoph
--
Microsoft SQL Server MVP
www.insidesql.org/blogs/cmu -
Den letzten Teil kann man natürlich auch noch etwas kürzen:
Select Twin, ProduktPaket1, ProduktPaket2, sum(case when Filiale = 'F1' then 1 else 0 end) as F1, sum(case when Filiale = 'F2' then 1 else 0 end) as F2, sum(case when Filiale = 'F3' then 1 else 0 end) as F3, count(distinct Filiale) as Anzahl_Filialen, count(*) as Anzahl_Kombi from cte group by Twin, ProduktPaket1, ProduktPaket2 order by Twin;
Einen schönen Tag noch,
Christoph
--
Microsoft SQL Server MVP
www.insidesql.org/blogs/cmu- Als Antwort markiert Jürgen Sch Freitag, 19. Oktober 2012 00:06
-
Hallo Jürgen,
ich würde es so machen:
SELECT 'P1_P2' AS Twin, COUNT(DISTINCT Filiale) AS AnzahlFilialen, COUNT(Filiale) AS AnzahlTwins FROM (SELECT Filiale, ProduktPaket1, ProduktPaket2 FROM test.dbo.tbl_Twins WHERE (ProduktPaket1 = N'P1') AND (ProduktPaket2 = N'P2') OR (ProduktPaket1 = N'P2') AND (ProduktPaket2 = N'P1')) AS Twin1 UNION ALL SELECT 'P1_P3' AS Twin, COUNT(DISTINCT Filiale) AS AnzahlFilialen, COUNT(Filiale) AS AnzahlTwins FROM (SELECT Filiale, ProduktPaket1, ProduktPaket2 FROM test.dbo.tbl_Twins WHERE (ProduktPaket1 = N'P1') AND (ProduktPaket2 = N'P3') OR (ProduktPaket1 = N'P3') AND (ProduktPaket2 = N'P1')) AS Twin2
Hallo Stephan,
danke erst einmal für deinen Lösungsvorschlag. Er funktioniert auch in so weit, dass die beiden Ergebnisspalten richtig generiert werden:
Twin AnzahlFilialen AnzahlTwins
P1_P2 2 4
P1_P3 1 1Allerdings fehlen die Zwischenergebnisse der Twins in den einzelnen Filialen. Außerdem setzt du die vorgegebenen Twins P1_P2 und P1_P3 in deiner Abfrage als gegeben voraus, was ich jedoch beim Start noch gar nicht weiß, d.h. diese sind dynamisch.
Gruß Jürgen
-
Hallo Christoph,
dein Vorschlag trifft wieder den Nagel auf den Kopf und liefert das gewünschte Ergebnis. Super!!!
Jetzt muss ich die Abfrage nur noch so umbauen, dass sie in bezug auf die Filialen dynamisch ist, weil die Namen der Filialen variabel sein können, diese bei deiner Lösung für die Summenbildung jedoch fest vorgegeben sind, oder hast du da noch schnell eine Anpassung parat?
Im Übrigen habe ich im November einen 2 wöchigen SQL-Lehrgang, wo ich hoffe, dass ich dann noch besser klar komme. :-)
Schönen Gruß und vielen Dank für deine Bemühungen.
Jürgen
-
Allerdings fehlen die Zwischenergebnisse der Twins in den einzelnen Filialen. Außerdem setzt du die vorgegebenen Twins P1_P2 und P1_P3 in deiner Abfrage als gegeben voraus, was ich jedoch beim Start noch gar nicht weiß, d.h. diese sind dynamisch.
Hallo Jürgen,
ich hatte deine Anforderungen anscheinend nicht richtig verstanden. Was solls, ich hatte dennoch meinen Spaß. ;-)
Da du schon eine Lösung hast, brauche ich mir ja keine weiteren Gedanken zu machen.
Gruß
Stephan