2009-09-10 2 views
1

У меня есть этот releases таблицы в базе данных SQLite3, перечисляя каждую выпущенную версию приложения:Присоединение к ограниченному подзапросу?

|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| 

Таким образом, для каждого APP_ID, будет несколько строками. У меня есть еще одна таблица, apps:

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

Я хочу, чтобы отобразить имя приложения и новый релиз, где «новые» означает (а) новейший RELEASE_DATE, и если есть дубликаты, (б) высокий release_id ,

я могу сделать это для индивидуального применения:

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 

но, конечно, ORDER BY применяется ко всему SELECT, запрос, и если я уйду из ИНЕКЕ, она по-прежнему возвращает только один ряд.

Это одноразовый запрос в небольшой базе данных, поэтому медленные запросы, временные таблицы и т. Д. В порядке - я просто не могу заставить свой мозг использовать SQL-способ сделать это.

ответ

1

Это легко сделать с помощью аналитической функции ROW_NUMBER(), который я думаю sqlite3 не поддерживает. Но вы можете сделать это таким образом, что это немного более гибким, чем то, что дано в предыдущих ответах:

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 
) 

Например, если у вас несколько столбцов упорядочивания, которые определяют «последнее,» MAX не будет работать для вас , но вы можете изменить подзапрос EXISTS, чтобы захватить более сложное значение «последнего».

+0

Мне это нравится, и я даже понимаю это - спасибо! –

0

Это некрасиво, но я думаю, что это будет работать

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 

Я надеюсь, что есть какой-то способ, чтобы получить оба этих столбцов в одной вложенной выбрать, но я не знаю его.

0

Try:

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 
1

Это проблема с наибольшей ошибкой в ​​группе. Он появляется несколько раз в неделю на StackOverflow.

Я обычно использую решение, как в @Steve Kass' answer, но я делаю это без подзапросов (я повадился лет назад с MySQL 4.0, которая не поддерживает подзапросы):

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; 

Внутренне это, вероятно, оптимизирует тождественно синтаксис NOT EXISTS. Вы можете проанализировать запрос с помощью EXPLAIN, чтобы убедиться.


Re свой комментарий, вы можете просто пропустить тест на release_date, потому что release_id является столь же полезным для установления хронологической последовательности выпусков, и я предполагаю, что это гарантированно будет уникальным, так это упрощает запрос:

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; 
+0

Оказывается, что некоторые из «дат выпуска» являются NULL, и это не нравится этим ... но это наиболее близко к моему ментальному представлению, поэтому это поможет мне понять, как эти различные запросы сопоставляются друг с другом. Благодаря! –

0

Err вторая попытка.Предполагая, что идентификаторы монотонно увеличиваются, а переполнение не является вероятным событием, вы можете игнорировать дату и просто делать:

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); 
Смежные вопросы