Выберите только последний вставленный элемент, относящийся к другому реестру

#mysql #sql

#mysql #sql

Вопрос:

Я смоделировал небольшую базу данных для упрощения объяснения:

 CREATE TABLE bands (
  id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  name VARCHAR(120) NULL,
  PRIMARY KEY(id)
)
TYPE=InnoDB;

CREATE TABLE albums (
  id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  band_id INTEGER UNSIGNED NOT NULL,
  album_name VARCHAR(120) NULL,
  rating INTEGER UNSIGNED NULL,
  insertion_date TIMESTAMP NULL,
  PRIMARY KEY(id),
  INDEX albums_FKIndex1(band_id),
  FOREIGN KEY(band_id)
    REFERENCES bands(id)
      ON DELETE NO ACTION
      ON UPDATE NO ACTION
)
TYPE=InnoDB;
  

Теперь, делая вид, что у нас уже есть несколько групп и много альбомов, зарегистрированных в соответствующих таблицах, я хочу выбрать ТОЛЬКО последний вставленный альбом из каждой зарегистрированной группы.

PS: Я должен использовать поле «album.insertion_date», чтобы определить, какой альбом вставлен последним.

Комментарии:

1. Может быть, вы можете вставить куда-нибудь ( gist.github.com ) небольшой дамп ваших вставок? Мне нужно выполнить проверку запроса.

2. Вы отметили вопрос как Postgresql, но ваш SQL четко показывает MySQL. Что вы используете?

3. Я использую postgres. Кажется, я экспортировал SQL в неправильном формате

Ответ №1:

Попробуйте объединить две таблицы и выполнить фильтрацию по insertion_date и band:

 SELECT al.*
FROM albums al
INNER JOIN bands b ON al.band_id=b.id
WHERE al.insertion_date=(
    SELECT max(insertion_date)
    FROM albums
    WHERE band_id=b.id
)
  

Комментарии:

1. ОШИБКА 1054 (42S22): неизвестный столбец ‘b.band_id’ в предложении ‘where’

2. Doliveras побеждает! поздравляю, и с хорошим временем выполнения (даже с базой данных, заполненной 18980 реестрами)

Ответ №2:

Попробуйте этот:

 select b.name, a.album_name, a.isertion_date
  from bands b, albums a
  where a.band_id = b.id
    and a.insertion_date = (select max(a1.insertion_date) from albums a1 where a1.band_id = b.id)
  

Комментарии:

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

Ответ №3:

Учитывая, что у вас есть идентификаторы альбомов, которые должны быть AUTO_INCREMENT и возможность того, что они insertion_date должны быть NULL (поскольку это значение по умолчанию), использование insertion_date для определения результатов — не самая разумная вещь, но … вот и все:

 SELECT DISTINCT band, last_album, insertion_date
FROM (
      SELECT bands.name AS band, albums.album_name AS last_album, albums.insertion_date
      FROM bands
       JOIN albums ON bands.id=albums.band_id
      ORDER BY albums.insertion_date DESC
     ) t1
GROUP BY band;
  

Комментарии:

1. имя_альбома отсутствует в предложении group by, поэтому mysql может свободно возвращать любое имя_альбома в пределах того же диапазона, это может быть не тот, у которого max insertion_date

2. Это не проблема при использовании ORDER BY , но в любом случае это было неправильно … итак, я просто отредактировал его.

3. Об использовании даты вставки для выбора последнего реестра: К сожалению, я не был ответственным за миграцию базы данных. Реестры новой базы данных не были вставлены в том же порядке, что и реестры из старой базы данных. Это отстой, но это нужно было сделать.

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