Frage

Ich habe diese releases Tabelle in einer SQLite3 Datenbank, jede freigegebene Version einer Anwendung Listing:

|release_id|release_date|app_id|
|==========|============|======|
|      1001| 2009-01-01 |     1|
|      1003| 2009-01-01 |     1|
|      1004| 2009-02-02 |     2|
|      1005| 2009-01-15 |     1|

Also für jeden app_id, gibt es mehrere Zeilen sein. Ich habe eine andere Tabelle, apps:

|app_id|name    |
|======|========|
|     1|Everest |
|     2|Fuji    |

Ich mag den Namen der Anwendung angezeigt werden und die neueste Version, wobei „neueste“ bedeutet (a) neuester RELEASE_DATE, und wenn es Duplikate, (b) höchst release_id.

Das kann ich für eine einzelne Anwendung:

SELECT apps.name,releases.release_id,releases.release_date 
  FROM apps 
  INNER JOIN releases 
    ON apps.app_id = releases.app_id
  WHERE releases.release_id = 1003
  ORDER BY releases.release_date,releases.release_id
  LIMIT 1

aber das ist natürlich ORDER BY auf die gesamte SELECT-Abfrage gilt, und wenn ich die WHERE-Klausel weglassen, es gibt nach wie vor nur eine Zeile.

Es ist eine One-Shot-Abfrage auf einer kleine Datenbank, so langsame Abfragen, temporäre Tabellen usw. ist in Ordnung - ich kann einfach nicht mein Gehirn bekommen um den SQL-Weg, dies zu tun

.
War es hilfreich?

Lösung

Das ist einfach mit der analytischen Funktion ROW_NUMBER () zu tun, was ich denke, sqlite3 nicht unterstützt. Aber man kann es auf eine Weise tun, die etwas flexibler ist als das, was in den früheren Antworten gegeben hat:

SELECT
  apps.name,
  releases.release_id,
  releases.release_date 
FROM apps INNER JOIN releases 
ON apps.app_id = releases.app_id
WHERE NOT EXISTS (
-- // where there doesn't exist a more recent release for the same app
  SELECT * FROM releases AS R
  WHERE R.app_id = apps.app_id
  AND R.release_data > releases.release_data
)

Zum Beispiel, wenn Sie mehrere Ordnungs Spalten haben, die „latest“ MAX definieren würde nicht für Sie arbeitet, aber man konnte ändern die EXISTS subquery die kompliziertere Bedeutung zu erfassen „latest.“

Andere Tipps

Dies ist die „größte N pro Gruppe“ -Problem. Es kommt mehrmals pro Woche auf Stackoverflow.

ich in der Regel eine Lösung, wie die in @Steve Kass' beantworten , aber ich tue es ohne Unterabfragen (ich in die Gewohnheit, vor Jahren bekam mit MySQL 4.0, den Unterabfragen nicht unterstützt):

SELECT a.name, r1.release_id, r1.release_date
FROM apps a
INNER JOIN releases r1
LEFT OUTER JOIN releases r2 ON (r1.app_id = r2.app_id 
  AND (r1.release_date < r2.release_date
    OR r1.release_date = r2.release_date AND r1.release_id < r2.release_id))
WHERE r2.release_id IS NULL;

Intern dies wahrscheinlich optimiert identisch mit der NOT EXISTS Syntax. Sie können die Abfrage analysieren mit EXPLAIN sicher zu machen.


Re Ihren Kommentar, Sie könnten nur den Test für release_date überspringen, weil release_id für die Festlegung der Reihenfolge der Veröffentlichungen ebenso nützlich ist, und ich nehme an, es ist garantiert einzigartig sein, so dass dies vereinfacht die Abfrage:

SELECT a.name, r1.release_id, r1.release_date
FROM apps a
INNER JOIN releases r1
LEFT OUTER JOIN releases r2 ON (r1.app_id = r2.app_id 
  AND r1.release_id < r2.release_id)
WHERE r2.release_id IS NULL;

Es ist hässlich, aber ich denke, es wird funktionieren

select apps.name, (select releases.release_id from releases where releases.app_id=apps.app_id order by releases.release_date, releases.release_id), (select releases.release_date from releases where releases.app_id=apps.app_id order by releases.release_date, releases.release_id) from apps order by apps.app_id

Ich hoffe, es gibt eine Möglichkeit, diese beiden Spalten in einem eingebetteten wählen zu bekommen, aber ich weiß es nicht.

Versuchen:

SELECT a.name,
       t.max_release_id,
       t.max_date
  FROM APPS a
  JOIN (SELECT t.app_id,
               MAX(t.release_id) 'max_release_id',
               t.max_date
          FROM (SELECT r.app_id,
                       r.release_id,
                       MAX(r.release_date) 'max_date'
                  FROM RELEASES r
              GROUP BY r.app_id, r.release_id)
      GROUP BY t.app_id, t.max_date) t

Err zweiten Versuch. Unter der Annahme, dass IDs monoton steigen und Überlauf ist kein wahrscheinliches Auftreten, können Sie das Datum ignorieren und einfach tun:

SELECT apps.name, releases.release_id, releases.release_date 
FROM apps INNER JOIN releases on apps.app_id = releases.app_id
WHERE releases.release_id IN 
(SELECT Max(release_id) FROM releases
GROUP BY app_id);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top