Runden von zahlen auf die nächsten 10 in Postgres
Ich versuche zu lösen dieses problem aus PGExercises.com:
https://www.pgexercises.com/questions/aggregates/rankmembers.html
Der Kern der Frage ist, dass ich eine Tabelle von Vereinsmitgliedern und halbe Stunde Zeit-slots, die Sie gebucht haben (die Liste ist eine einfache INNER-JOIN von zwei Tabellen).
Ich soll produzieren eine absteigende Rangfolge der Mitglieder durch Gesamtzahl der Stunden gebucht, gerundet auf die nächsten 10. Ich muss auch zum erzeugen einer Spalte mit dem Rang, mit dem RANK()
Fenster-Funktion, und Sortieren Sie das Ergebnis nach dem Rang. (Das Ergebnis ergibt 30 Datensätze.)
Des Autors sehr elegante Lösung ist diese:
select firstname, surname, hours, rank() over (order by hours) from
(select firstname, surname,
((sum(bks.slots)+5)/20)*10 as hours
from cd.bookings bks
inner join cd.members mems
on bks.memid = mems.memid
group by mems.memid
) as subq
order by rank, surname, firstname;
Leider als SQL-newbie, meine sehr unelegant Lösung ist viel mehr kompliziert, mit CASE WHEN
und Umwandlung von zahlen in text um sich die Letzte Ziffer für die Entscheidung, ob der Runde bis oder unten:
SELECT
firstname,
surname,
CASE
WHEN (SUBSTRING(ROUND(SUM(slots*0.5),0)::text from '.{1}$') IN ('5','6','7','8','9','0')) THEN CEIL(SUM(slots*0.5) /10) * 10
ELSE FLOOR(SUM(slots*0.5) /10) * 10
END AS hours,
RANK() OVER(ORDER BY CASE
WHEN (SUBSTRING(ROUND(SUM(slots*0.5),0)::text from '.{1}$') IN ('5','6','7','8','9','0')) THEN CEIL(SUM(slots*0.5) /10) * 10
ELSE FLOOR(SUM(slots*0.5) /10) * 10
END DESC) as rank
FROM cd.bookings JOIN cd.members
ON cd.bookings.memid = cd.members.memid
GROUP BY firstname, surname
ORDER BY rank, surname, firstname;
Trotzdem Schaffe ich es fast bekommen es genau das richtige - von den 30 Datensätzen, bekomme ich einen Grenzfall, dessen Vorname ist 'Nachdenken' und lastname ist 'Stephens'. Seine gerundete Anzahl der Stunden ist 124.5
, aber die Lösung besteht darauf, dass die Runden auf den nächsten 10 sollte ein Ergebnis von 120
, während meine Lösung produziert 130
.
(By the way, gibt es einige andere Beispiele, wie 204.5
Aufrundung auf 210
sowohl in der mine und die Ausübung des Autors Lösung.)
Was ist Los mit meinem Rundung Logik?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie wollen, um Runden auf die nächsten 10, dann verwenden Sie den eingebauten
round()
Funktion:Das zweite argument negativ ist, mit -1 für tens, -2 für Hunderte, und so weiter.
Runde der nächsten mehrere der
10
:die Runde bis für die Werte der Endung 5-9, unten sonst.
Diese hat die Allgemeine Formel:
So konnte man Runden auf den nächsten
13
wenn Sie wollte.SELECT round(105 / 50 + .5) * 50
geben150
statt100
.Ich habe gekämpft, mit einem gleichen Problem. Ich brauchte, um die Runde Zahl auf das nächste Vielfache von 50. Gordon ' s Vorschlag funktioniert nicht.
Mein Erster Versuch war
SELECT round(120 /50) * 50
, die gibt100
. AllerdingsSELECT round(130 /50) * 50
gab100
. Dies ist falsch; das nächste Vielfache ist150
.Der trick ist, zu teilen mit einem Schwimmer, z.B.
SELECT round(130 /50.0) * 50
geben150
.Stellt sich heraus, dass dabei
x/y
, wox
undy
Ganzzahlen sind, ist äquivalent zutrunc(x/y)
. Wo als float-division, die korrekt rundet auf das nächste Vielfache.