SQL: Jede einfache Möglichkeit, die Ergebnisse zu ordnen ZUERST, DANN Gruppe durch eine andere Spalte?
Sehe ich, dass in SQL, GROUP BY muß vorausgehen, UM DURCH Ausdruck. Bedeutet dies, dass die Sortierung erfolgt nach der Gruppierung verwirft identische Zeilen/Spalten?
Da scheine ich zu brauchen, um Reihen von einer timestamp-Spalte Einer ersten, DANN verwerfen Zeilen mit gleichem Wert in Spalte a Nicht sicher, wie dies zu erreichen...
Ich bin mit MySQL 5.1.41
create table
(
A int,
B timestamp
)
Die Daten könnten sein:
+-----+-----------------------+
| A | B |
+-----+-----------------------+
| 1 | today |
| 1 | yesterday |
| 2 | yesterday |
| 2 | tomorrow |
+-----+-----------------------+
Den Ergebnissen, die ich am Ziel wäre:
+-----+-----------------------+
| A | B |
+-----+-----------------------+
| 1 | today |
| 2 | tomorrow |
+-----+-----------------------+
Grundsätzlich möchte ich die Zeilen mit dem aktuellen timestamp in die Spalte B (denkt UM), und nur eine Zeile für jeden Wert in Spalte A (denken, DISTINCT-oder GROUP BY).
Meinem eigentlichen Projekt-details, wenn Sie diese:
Im wirklichen Leben, ich habe zwei Tabellen - users
und payment_receipts
.
create table users
(
phone_nr int(10) unsigned not null,
primary key (phone_nr)
)
create table payment_receipts
(
phone_nr int(10) unsigned not null,
payed_ts timestamp default current_timestamp not null,
payed_until_ts timestamp not null,
primary key (phone_nr, payed_ts, payed_until_ts)
)
Den Tabellen können auch andere Spalten, die ich weggelassen alle, die IMO ist hier irrelevant. Als Teil einer mobile-payment-scheme, habe ich senden SMS, um Benutzer über das mobile-Handy-Netz in regelmäßigen Abständen, abhängig natürlich, ob die Zahlung fällig ist oder nicht. Die Zahlung realisiert wird, wenn die SMS gesendet wird, die premium-besteuert. Ich Aufzeichnungen über alle Zahlungen im Zusammenhang mit der payment_receipts
Tabelle, für die Buchhaltung, die simuliert einen realen shop, wo sowohl Käufer und Verkäufer erhalten eine Kopie der Quittung, für die Referenz. Diese Tabelle speichert meine (Verkäufer), Kopie der Quittung. Die Kunden die Quittung der empfangenen SMS selbst. Jedes mal, wenn eine SMS gesendet wird (und damit eine Zahlung durchgeführt wird), wird die Tabelle eingefügt, ein Eingang Datensatz, die besagt, wer bezahlt, wenn und "bis Wann". Zu erklären, die letztere, sich vorstellen, ein Abonnement-service, aber eine die sich auf unbestimmte Zeit, bis eine Benutzer-opt-out " explizit, an welchem Punkt der Benutzer-Datensatz wird entfernt. Eine Zahlung ist einen Monat im Voraus, also in der Regel, der Unterschied zwischen den payed_ts
und payed_until_ts
ist 30 Tage Zeit.
Natürlich habe ich ein batch-job, der ausgeführt wird, jeden Tag und muss wählen Sie eine Liste von Benutzern, die durch monatliche Zahlung als Teil der automatischen Abo-Erneuerung. Link zu dieser den dummy-Beispiel weiter oben, die Telefon-Nummer Spalte phone_nr
ist a
und payed_until_ts
ist b
, aber in der aktuellen code gibt es zwei Tabellen, die bringen mich zu dem folgenden Verhalten und seine Auswirkungen: wenn ein Benutzer-Datensatz entfernt wird, der Empfang bleibt für die Buchführung. Also, nicht nur muss ich die Gruppe Zahlungen nach Datum und entsorgen Sie alle, aber die Letzte Zahlung Datum des Eingangs, ich muss auch aufpassen, nicht zu wählen, Quittungen, wo es nicht mehr der passende Benutzer-Datensatz.
Ich bin der Lösung des Problems der Auswahl der Datensätze, die aufgrund der Zahlung durch die Suche nach dem belegen mit den neuesten payed_until_ts
- Wert (wie in den meisten Fällen wird es mehrere Zugänge für jeden Handy-Nummer) für jede phone_nr
und aus diesen Zeilen, die ich weiter verlassen müssen nur die phone_numbers, wo die payed_until_ts
ist älter als die Zeit der batch-job ausgeführt wird. Ich Schleife über die Liste dieser Nummern und verschickt Zahlungen, also eine neue Bestätigung für jedes gesendete SMS, wo payed_ts
ist now()
und payed_until_ts
ist now() + interval 30 days
.
The tables may include other rows
? Kommen wieder?Es hätte geschrieben 'Spalten', natürlich. Ich habe korrigiert. Vielen Dank für Flecken es aus.
InformationsquelleAutor amn | 2010-07-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
haben Sie noch nie gehört von einer Unterabfrage: dev.mysql.com/doc/refman/5.0/en/subqueries.html
Sherov & andere Erste Fehler ist, dass Sie versuchen, zum anzeigen der Spalte B, die nicht aggregiert und nicht in der GROUP BY-Klausel... Zweitens, dass die sub auswählen, die Sie verwenden, funktioniert in Oracle und MySql byt in sql server nicht, dennoch ist diese Bestellung ist Fall nutzlos ist. Die Tabellen sind Sätze so zu verstehen, Lesen Sie über die set-Theorie.
Sie können diese optimieren, weitere:
select * from (select users.phone_nr as phone_nr, p.payed_until_ts as payed_until_ts from users inner join payment_receipts using (phone_nr) where payed_until_ts < now() order by payed_until_ts desc) as t group by phone_nr;
Dies zu tun, fügen, Bestellung, und, wo in einem Durchlauf, und führen Sie dann die Gruppe, indem Sie danach. Ich habe es noch nicht getestet, und vorausgesetzt, es gibt keine syntax-Fehler, es könnte schneller sein.Obwohl dies die akzeptierte Antwort, es ist falsch, denn es verwendet eine MySQL-Erweiterung, die
select
sind nicht in dergroup by
(siehe dev.mysql.com/doc/refman/5.6/en/group-by-handling.html).InformationsquelleAutor Mike Sherov
Ja, ist die Gruppierung zum ersten mal getan, und es wirkt sich auf eine einzelne
select
in der Erwägung, dass die Bestellung betrifft alle Ergebnisse aus allenselect
Aussagen in einemunion
wie:(mit Feld-Nummern in
order by
da konnte ich nicht die Mühe gemacht, die Namen meiner Spalten). Jedergroup by
wirkt sich nur auf seineselect
, dieorder by
wirkt sich auf das Ergebnis aus der Kombination festgelegt.Es scheint, dass das, was Sie suchen, können erreicht werden mit:
Diese nutzt die
max
aggregation-Funktion, die im Grunde tun Sie Ihre pre-Gruppe Ordnung (es muss nicht eigentlich Art, die es in jedem anständigen DBMS, sondern es wird einfach wählen Sie die maximale von einem geeigneten index, wenn verfügbar).Nicht sicher, was du meinst, @Mike. Dadurch wird die gesamte Zeile. Wenn Sie extra Spalten, die Sie wollen, zog aus der Zeile mit der höchsten
B
dann, ja, Sie brauchen einen anderen Weg, da Sie zu benutzen, eine aggregation-Funktion und es kann ein Wert aus einer anderen Zeile. So ist ein Albtraum, der in standard-SQL und sollte wahrscheinlich verlassen werden zu einem höheren (D. H., Applikations -) Schicht.ja, es erfordert eine subselec wenn Sie möchten, dass andere Werte aus der Zeile mit der max(b), die ich Stimme ist ein Alptraum (riesige möglichen temp-Tabelle). Ich würde, denke aber, dass es in der app. Ebene wäre ein noch größerer Albtraum 🙂
Sie haben eine sehr nützliche Antwort, und ich habe bestätigt, es funktioniert sehr gut für mich. Der einzige Nachteil hier ist, dass muss man sich bewusst sein, dass dies NICHT funktionieren (wie von anderen erwähnt), wo es andere Spalten abgerufen werden neben
a
undmax(b)
. Da ich Plane, um schließlich wählen Sie weitere Spalten wie gut, daß ich nicht verwenden Ihre Lösung. Aber wollte sagen, ein großes danke dennoch für gewisse Szenarien, die es gilt perfekt!Keine probs, @amn. Meine Lösung ist gut für die Frage aber, wie du sagst, problematisch, wenn Sie möchten, dass andere Spalten aus der gleichen Zeile.
InformationsquelleAutor paxdiablo
InformationsquelleAutor nvogel
Nach Ihren neuen Regeln (getestet mit PostgreSQL)
Abfrage, die Sie Wollen:
Ursprüngliche Antwort (mit updates):
Kommentar:
1
zurückgegeben, zweimal, denn es sind mehrereb
Werte. Dies ist akzeptabel (und ratsam). Ihre Daten sollten Sie nie dieses problem haben, weilc
basiert aufb
's Wert.max
- wenn es andere Spalten abrufen, die neben denmax
unda
bin ich mir nicht sicher, in welcher Zeile wird diese zurückzugeben.könnten Sie ein wenig mehr beschreibend in dem, was Sie versuchen zu erreichen? haben Sie keine Angst um Ihr Beispiel ein wenig mehr explizit - SO ist gefüllt mit Programmierern, die durch alle Ebenen der Programmierung.
group by
Gruppen auf eine Reihe von Tasten, um wieder eine eindeutige Gruppe von Werten. wenn Sie möchten, um mehr Spalten zurück, in derselect
undgroup by
Hallo, ich habe einen ganzen Abschnitt mit dem eigentlichen problem, für Ihr "Vergnügen" 🙂 vielen Dank für Ihre Zeit. Das update würde nicht gelten, weil es keine zwei Datensätze mit doppelten
a
können in den Ergebnissen angezeigt.Ich habe zu einer Hochzeit gehen, so kann ich nicht überprüfen, diese eine weitere, aber mein review aktualisieren, bevor Sie sagen, es nicht anzuwenden. Ich gab das Szenario, dass die Spalte
b
(alle Ihre hinzugefügten Spalten) könnte das gleiche Spaltea
und dasselbe Datum. Sie müssen möglicherweise Daten/system-Einschränkungen, um zu verhindern, dass dies geschieht, aber die Abfrage würde noch sein, was Sie brauchen.Ich bin mir nicht sicher, warum Sie wählte die Antwort, die du hast, aber die oben genannten sollten tun, was Sie brauchen, basierend auf Ihren vorherigen Frage. Ich versuche nicht, um Antwort auf Ihre andere Frage, weil ich nicht wollen, um einen Beitrag zu löschen "nutzlosen" Einträge, da ich glaube, keine der Informationen ist nutzlos. Wenn Sie zum extrahieren von Daten aus einer Tabelle, dann müssen Sie entweder 1) Ihre Anwendung ändern oder 2) ändern Sie Ihre Datenbank (hinzufügen von Triggern) / logging (aufzeichnen), so dass die Informationen dort platziert, wo es sein muss. Ich schlage vor, mit einem
update
Abfrage und die richtige Trigger/logsInformationsquelleAutor vol7ron
Im obigen Beispiel, das ich verwendet habe, datetime-Spalte ist, aber ähnliche Abfrage sollte funktionieren, für die timestamp-Spalte.
Die MAX-Funktion wird im Grunde tun die "ORDER BY" payed_until_ts Spalte und wählen Sie den aktuellen Wert für jeden phone_nr.
Auch Sie erhalten nur einen Wert für jeden phone_nr durch "GROUP BY" - Klausel.
InformationsquelleAutor vartaks