Select: Count verschiedener Spalten

MysterioJN

SQL-Guru
Beiträge
158
Hi,

bestimmt easy, aber ich stehe gerade eine gewisse Zeit derbe auf dem Schlauch. Auch mittels VB/Access bekomm ich folgende Abfrage gerade nicht nicht:

Vorhandene Tabelle:
"Adressen"

Relevante Spalten:
"Branche" (Int-Feld)
"Werbung_Post" (True/False-Feld)
"Werbung_Email" (True/False-Feld)

Beispieldatensätze an Hand folgender Spalten: Vorname, Name, Branche, Werbung_Post, Werbung_Email

Anton, Muster, 200, Ja, Nein
Berta, Muster, 130, Nein, Nein
Clementine, Muster, 130, Nein, ja
Dora, Muster, 130, Ja, Ja


Ziel soll es sein, das er mir die Anzal von Kundenadressen nennt, die
1. gruppiert nach "Branche" sein sollen
2. die Anzahl der KundenDatensätze der jeweiligen Branche, die Werbung_Post = True
3. die Anzahl der KundenDatensätze der jeweiligen Branche, die Werbung_EMail = True


So sollte dann das Beispielergebnis aussehen nach Spalten:

Branche, AnzKundenPost, AnzKundenEMail
200, 1, 0 (Hierbei handelt es sich nur um Anton Muster)
130, 1, 2 (Hierbei handelt es sich um Berta, Clementine und Dora Muster)

Die Anzahl je nach Stammdatenvorgabe (true/false)
 
Werbung:
Code:
Select branche
      ,Sum(Case
              When werbung_post = 'TRUE' Then
               1
              Else
               0
           End) As werbung_post
      ,Sum(Case
              When werbung_email = 'TRUE' Then
               1
              Else
               0
           End) As werbung_email
From   adressen
Group  By branche
Würdest du ein numerisches Flag (1 und 0) verwenden, wäre die Abfrage etwas schöner...
 
Perfekt!!! Klappt prima. Danke euch beiden (mal wieder).

Wobei mich das noch zu einem andern Punkt führt:

Beispiel:
Select.....
format(sum(stück),0,'de_DE')
From ....

Dann gibt er mir das Ergebnis der Summe als ganze Zahl aus.

Anderes Beispiel:
format(sum(umsatz),2,'de_DE')

Dann gibt er mir die Summe mit zwei Nachkommastellen, Komma als Centtrennung und Punkt als Tausendertrennung aus.


Jetzt habe ich aber eine SUM(CASE Bedingung und da klappt das Formatieren komischerweise nicht:

Sum(CASE
WHEN tab.art='storniert'
THEN Format((tab.st * -1),0,'de_DE')
ELSE Format((tab.st),0,'de_DE')
END) AS Absatz,

Tut mir echt leid das ich so "blöde" Fragen stellen muss, aber wenn mich am Tag zahlreiche Mitarbeiter ansprechen, das deren Excelexport der Daten nicht die entsprechenden Formate mitliefern (Beispiel kommatrennung durch nen Punkt, etc.) und somit keine Summenfunktionen in Excel (zumindest nicht ohne suchen und ersetzen, bzw. formatieren der Spalten) möglich sind, nervt mich meine Unwissenheit schon stark ab hinsichtlich SQL.
 
Code:
format(sum(umsatz),2,'de_DE')
Hier formatierst du das Ergebnis der Summen-Funktion

Code:
Sum(CASE
WHEN tab.art='storniert'
THEN Format((tab.st * -1),0,'de_DE')
ELSE Format((tab.st),0,'de_DE')
END) AS Absatz,
Hier formatierst du den zu summierenden Wertebereich

Erkenne den Unterschied :)
 
Arghhh ja du hast recht.

Mit

format(Sum(CASE
WHEN tab.art='storniert'
THEN tab.st*-1
ELSE tab.st
END) ,'0','de_de') ASAbsatz,

klappte es endlich....
 
Kannst du mir im Case Fall nochmal einen Tritt geben:

Kleine andere Ausgangssituation:
Tabelle (rowid, Art, ...):
1, Bestellung, ...
2, Storno, ...
3, Bestellung, ...

Ich brauch die ANZAHL (Count?) der tatsächlich rechtskräftigen Bestellungen (Ganzzahl). Sprich wenn ich über die Tabelle ein Count(*) setzte, gibt er mir "3" aus. Da aber eine Stornierung dabei war, soll diese abgezogen werden.

Sprich in Excel würde ich es so bauen:
=zählenwenn(Art;"Bestellung") - zählenwenn(Art;"Storno") = Ergebnis: "1"
 
Code:
Select Sum(Case
              When art = 'Bestellung' Then
               1
              When art = 'Storno' Then
               -1
              Else
               0
           End)
From   andere_tabelle
Es ginge wohl mit 2 Count's und nem Join... Das hier müsste aber eig. schneller sein... Behaupte ich einfach mal :)

Edit:
Das hier würde evtl. vorhandene Indizes nutzen...
Code:
Select Sum(Case
  When art = 'Bestellung' Then
  col
  When art = 'Storno' Then
  col * -1
  Else
  0
  End)
From  (Select art
  ,Count(*) As col
  From  andere_tabelle
  Group  By art)
 
Zuletzt bearbeitet:
YESSSSS ! Du bist meine Urlaubsrettung!!! Hier nun der komplette Select dank deiner Hilfen hier im Thread:

Code:
SELECT ra AS Rabattstaffel,
format(Sum(Case
        When tab.art = 'selektiert' Then
               1
          When tab.art = 'storniert' Then
               -1
              Else
               0
           End),'0','de_de') As Bestellungen,

format(Sum(CASE
    WHEN tab.art = 'storniert'
    THEN tab.st *-1
    ELSE tab.st
    END),'0','de_de') AS Absatz,

format(Sum(CASE
    WHEN tab.art = 'storniert'
    THEN round((tab.preis - (tab.preis*tab.ra/100))*tab.st,2)*-1
    ELSE round((tab.preis - (tab.preis*tab.ra/100))*tab.st,2)
    END),'2','de_de') as Umsatz

FROM tab

WHERE (art = 'selektiert' AND rd BETWEEN '2015-01-01' AND '2015-12-31') OR (art = 'storniert' AND rd BETWEEN '2015-01-01' AND '2015-12-31')
group by 1


Es könnte so einfach sein, wenn die Datenbank des Dienstleisters nicht so ein Chaos wäre...

Jetzt wissen wir, was über den Dienstleister an Bestellungen, Absätze in Stück und Umsätze generiert wurden ABZGL. der Stornierungen (die Datensatzmäßig wie eine Bestellung mit "+" erfasst werden^^)

Genial!!!!

Kommst nicht aus der Nähe Bonn und gibt's Nachhilfe oder?! ;))
 
Ich muss jetzt aber gerade nochmal nachfrage... Wo ich mir dein Statement angeguckt habe ist mir aufgefallen dass dein Beispiel:
=zählenwenn(Art;"Bestellung") - zählenwenn(Art;"Storno") = Ergebnis: "1"
Falsch ist (genauso wie meine Antwort...)...

Oder willst du wirklich die Differenz von Bestellungen zu Stornierungen? ...

Du schreibst ja, das du alle "rechtskräftigen Bestellungen" willst... das wären dann ja 2 oder?
 
Naja, das Problem ist, das der Vertrieb für jeden Vorgang eine Datenzeile in der Bestellungstabelle anlegt:

- rowid 1, Selektiert (Bestellungseingang), 2015_15 (Rechnungsnummer)
- rowid 2, Selektiert (Bestellungseingang), 2015_16 (Rechnungsnummer)
- rowid 3, bezahlt (Bestellungsbezahlung), 2015_15 (Rechnungsnummer)
- rowid 4, storniert (Bestellungsstornierung/Retour), 2015_16 (Rechnungsnummer)

Die Rechnungsnummer ist die Referenzierung der Datensatzvorgänge.

Wenn ich nun sage, zeige mir nur die summe (Umsatz, Absatz) oder Anzahl Bestellungen bei Art = "selektiert" an, sind das zwar theoretisch aufgegebene Bestellungen (hier 2),
die aber auch storniert worden sein können vom Kunden (hier 1). Somit ist tastächlich fakturiert nur "1".


Mein nächster Schritt wird sein, mir nur tatsächlich fakturierte Datensätze anzeigen zu lassen.
Sprich Datensätze, die "storniert" wurden und an Hand der Rechnungsnummer somit auch den Datensatz der "selektiert" ausblenden.
Wie ich das hinbekommen weiß ich gerade noch nicht. Ich werde mir aber mittels Accessabfragen (--> SQL anzeigen), Übernahme in MSSQL und dem hoffentlich hier verstandenen Wissen deiner vorherigen Posts versuchen, es selbst hinzubekommen.
 
Distrilec ich muss dir nochmal auf die Nerven gehen (muss das bis morgen fertig haben da dann 2 Wochen Urlaub).
Ich verzweifel hier am Verständnis einer Select in Select Abfrage (die ich aber auch mit Access nicht zum gewünschten Ergebnis bekomme)

Situation:
Tabelle "tab"
Spalten: Art, Artikelkennung, ....

Tabelle "Artikel"
Spalten: Artikelkennung, Status

Zunächst ALLE Datensätze aus der tab mit der Art = "selektiert" anzeigen lassen:
SELECT * FROM tab WHERE Art = 'selektiert'

Jetzt will ich den Select mit der Tabelle Artikel verknüpfen ABBBER es gibt keine eindeutige VerknüpfungsID.
Die "Artikelkennung" kommt x-mal in der "tab" (was richtig sein kann) vor und leider auch x-mal in der "Artikel" (was nicht sein dürfte).
Daher soll als zusätzliches Kriterium der Status = "Aktuell" aus der Tabelle "Artikel" genutzt werden, damit ich den richtigen Datensatz aus der "Artikel" ausgebe.
Denn, es gibt zwar mehrere Datensätze mit der Artikelkennung in der "Artikel", aber jeweils nur einen mit Status "aktuell".
Es kann aber durchaus vorkommen, das es Artikelkennungen gibt, die auch keinen Status "aktuell" haben (sprich alte Artikel).

Wenn ich mir mit Access diese Abfrage baue, zeigt er mir aber nur noch die Datensätze an, die tab.Art = 'selektiert' UND Artikel.Status = 'aktuell' sind an, obwohl ich sage, zeige ALLE Datensätze der tab an und nur sofern vorhanden die der Artikel.


Hier die Vorgabe unseres Dienstleisters, die ich aber einfach nicht kapiere im Aufbau una auch bzgl. der komischen kürzel d und t:

SELECT (
SELECT ag
FROM artikel d
WHERE d.Status = 'aktuell' AND d.aken=t.aken
FROM tab t
WHERE
t.art = 'selektiert' AND t.aken IN(
SELECT aken
FROM artikel
WHERE STATUS = 'aktuell')




Ich versteh einfach nicht, warum ich mich mit verschachtelten Selects so schwer tue und sie nicht "lesen" kann. In Excel baue ich um ein vielfaches verschachtelte mit Einbeziehung diverser Funktionen die Formeln auf. Und hier verzweifel ich so kläglich...
 
Zuletzt bearbeitet:
Werbung:
1: Das Beispiel deines Dienstleister ist total falsch... Alleine schon die Syntax ;)
2: Das ist wahrscheinlich das, was du suchst...
Code:
Select *
From   tab t

Left   Join artikel a
On     a.aken = t.aken
And    a.status = 'aktuell'

Where  t.art = 'selektiert'
Zeigt alle Datensätze in deiner Tabelle "art" und falls vorhanden auch die Datensätze in der Tabelle "artikel" (mit entsprechendem "aktuell" status)

Wenn du dich in Zukunft intensiver mit SQL/Datenbanken beschäftigen musst empfehle ich eine professionelle Schulung :)
(Oder du wühlst dich tagelang durch google-Ergebnisse... Ist aber eher eine Notlösung)

Edit: 3: Die Kürzel die dein Dienstleister verwendet hat (oder zumindest wollte?) sind nichts weiter als Aliase. Sie werden gesetzt sobald man mehr als eine Tabelle hat, damit man den kompletten Tabellennamen nicht immer ausschreiben muss.
Ohne Kürzel sieht mein obiges Statement z.b. so aus:
Code:
Select *
From   tab

Left   Join artikel
On     artikel.aken = tab.aken
And    artikel.status = 'aktuell'

Where  tab.art = 'selektiert'
Macht das ganze einfach nur unnötig unübersichtlich...
 
Zurück
Oben