SQL Aggregieren von mehreren werten mit ein Anzahl an gleichen Werten

Status
Für weitere Antworten geschlossen.

Huri57

Cadet 2nd Year
Registriert
Mai 2020
Beiträge
23
Hier 2 Outputs aus 2 Abfragen:

Output 1:
durationallWorkItems
between 15 and 60 min56
bigger than 60 min39

Output 2:
durationfinishedWorkItems
between 15 and 60 min19
bigger than 60 min28

Nun möchte ich "finishedWorkItems" durch "allWorkItems" teilen, um einen Prozentsatz zu bekommen. In vereinfachten Code würde ich das so machen:
SQL:
SELECT CASE

WHEN strftime('%s', end) - strftime('%s', beginning) < 15*60 THEN 'smaller than 15 min'

WHEN  strftime('%s', end) - strftime('%s', beginning) BETWEEN 15*60 AND 60*60 THEN 'between 15 min and 60 min'

ELSE 'more than 60 min' END AS duration,

**(COUNT(task_id WHERE finished = true)/COUNT(task_id)) finishingRate**

FROM

[..](Ich denke die Abfrage wäre zu lang; ich pack sie aber unten nochmal vollständig hin)

GROUP BY 1

Leider funktioniert es nicht so einfach, wie hier oben oder doch? Ich hab es mit subqueries versucht, was aber nicht geklappt hat.
Hat jmd eine Idee, wie man es machen könnte?
Der gewünschte Output würde folgendermaßen ausschauen:

DurationfinishingRate
between 15 and 60 min0,33
bigger than 60 min0,71


Hier noch der vollständige Code:
SQL:
1.    SELECT CASE
WHEN strftime('%s', ende) - strftime('%s', anfang) < 15*60 THEN 'kleiner als 15 min'
WHEN  strftime('%s', ende) - strftime('%s', anfang) BETWEEN 15*60 AND 60*60 THEN 'zwischen 15 min und 60 min'
ELSE 'größer als 60 min' END AS Dauer,
COUNT(Aufgabe.Aufgabe_ID) erledigteAufgaben
FROM
(SELECT COUNT(k_id), k_id, Nutzer._Id, Nutzer.Name
FROM Nutzer
JOIN Kalender
ON Nutzer._Id = Kalender.nutzer_id
JOIN Ereignis
ON Ereignis.K_ID = Kalender.Name
GROUP BY k_id, nutzer_id, Nutzer.name
ORDER BY 1 DESC
LIMIT 1) AS sub
JOIN Ziel
ON sub._id = Ziel.Nutzer_ID
JOIN Aufgabe
ON Ziel.Ziel_ID = Aufgabe.ziel
!!Aufgabe.fertig = true!!
GROUP BY 1

Und hier noch das Diagramm für die Beziehungen:
1622985759092.png
 
Hey Huri57,

kann ich dich fragen WARUM du das alles innerhalb des SQL Statements machen möchtest? Gibt es dafür einen zwingenden Grund?

Ich hab schon einiges mit SQL gemacht (von einfachen Abfragen bis hin zu Abfragen über hunderte von Millionen Einträgen) und meiner Erfahrung nach ist das, was du vorhast, ein Antipattern. SQL ist exzellent um mit großen Daten (Zeilenweise) zu arbeiten, es ist jedoch furchtbar schlecht um einzeln, spaltenbasiert oder verkettet (Tree-artig) zu arbeiten.

Ich würde folgendes machen:
1. Query deine jeweiligen Informationen (deine beiden Outputs, ist ja soweit schon fertig)
2. Spalten kompatibler benennen (z.B. AllWorkitemsMax60Minutes, AllWorkitemsAbove60Minutes, FinishedWorkitemsMax60Minutes, FinishedWorkitemsAbove60Minutes)
3. Keinerlei Programmlogik in SQL verwenden und deswegen die jeweiligen Berechnung auf deine primäre Anwendung auslagern.
 
  • Gefällt mir
Reaktionen: Huri57
Hi Andy_0,
vielen Dank für deine ausführliche Antwort!

Eigentlich würde ich so nie SQL-Abfragen in der Praxis machen(für die Verarbeitung der Rohdaten ist SQL ja wie du auch sagst nicht gedacht) , aber in der Schule wurden möglichst verkettete und verzwickte Abfragen gefordert…

Die bessere Benennung der Spalten ist aber eine sehr gute Idee; sonst ist das weiterarbeiten an der Abfrage ziemlich mühsam.

Falls jmd. doch so ein Antipattern (für die Schule) benötigt, ist hier der Lösungsansatz, den ich durch etwas Hilfe rausbekommen habe:

SQL:
with q1 as (< query 1 here>),
     q2 as (< query 2 here>)
select q1.duration, q2.finishedWorkItems / q1.finishedWorkItems
from q1 join
     q2
     on q1.duration = q2.duration;
 
Status
Für weitere Antworten geschlossen.
Zurück
Oben