2013-11-26 4 views
3

Что я ищу, чтобы сделать это ...Получение большинства последних записей в группах

У меня есть база данных, которая регистрирует изменения в статусе записи ...

Например, он может быть установлен как «неактивные», а затем, в более поздней строке может активировать запись ...

1 Company1 Active 
2 Company2 Active 
3 Company1 Inactive 
4 Company1 Active 

запрос нужно искать активных в данный момент результаты ... и должны вернуть две записи ... (один для company1 и один для Company2.)

Мне нужно вернуть только те записи, которые в настоящее время активны.

Этот запрос делает его часть ...

SELECT id, gid, status 
FROM companies 
GROUP BY gid 
HAVING status = 'Active' 
ORDER BY id 

Но он не ищут возвращаемые результаты на основе последней записи ...

То, что я в основном смотрел на то, как чтобы включить в каждую группу только самую последнюю запись, такую ​​как «LIMIT 1,1» с «ORDER BY id DESC» ... Я понятия не имею, как включить ее в запрос.

Обновление Я добрался до так далеко ... На основании ответа, но это вернуть последнюю строку каждой группы, является ли она в настоящее время активна или нет ...

select t.* 
from (
    select status, max(id) as id 
    from companies 
    group by gid 
    having status = 'Active' 
) active_companies 
inner join companies t on active_companies.id = t.id 
+0

Я не вижу столбец в вашей таблице, который строго указывает порядок между вашими статусами, а не 'id', но это ненадежно. У вас есть столбец со значением «дата изменения статуса»? –

+0

Я уверен, что 'id' будет адекватен потребностям OP – Strawberry

ответ

2

Если ваши идентификаторы всегда в порядке возрастания, это будет выбран самый последний идентификатор для каждой компании :

SELECT MAX(id), gid 
FROM companies 
GROUP BY gid 

и это вернет все записи, которые вам нужны:

SELECT companies.* 
FROM companies INNER JOIN (SELECT MAX(id) m_id 
          FROM companies 
          GROUP BY gid) m 
    ON companies.id = m.m_id 
WHERE 
    status = 'Active' 

Вы также можете захотеть использовать эту маленькую хитрость:

SELECT * 
FROM (SELECT * FROM companies ORDER BY id DESC) t 
GROUP BY gid 
HAVING status='Active'; 

но пожалуйста не! Обычно он/чаще всего работает, он выглядит более чистым и часто быстрее, но полагается на недокументированное поведение, поэтому не гарантируется, что вы всегда получите правильный результат.

См. Скрипку here!

+0

Спасибо !!! Работает отлично! – user1182155

0

Попробуйте подвыборку получить записи, где статус = «Активный» и порядок по идентификатору (который я предполагаю, что это автоинкрементным) убывание затем в родителю выбрать сделать группу по

SELECT t.* FROM (
SELECT * 
FROM companies 
WHERE `status` = 'Active' 
ORDER BY id DESC 
) t 
GROUP BY t.gid 
+2

Это зависит от недокументированного поведения (если вы не подсчитаете раздел комментариев пользователей соответствующей страницы руководства) – Strawberry

+0

Я не думаю, что этот SQL удовлетворяет требованию« * Мне нужно вернуть только те записи, которые в настоящий момент активны. * ". AFAICS, этот запрос вернет последнюю активную запись для группы, которая в настоящее время неактивна. –

1

Давайте разделить задачу на две меньшие:

во-первых, вы хотите, чтобы получить самую последнюю запись из каждая группа:

select max(id) 
from companies 
group by gid; 

Далее, вы хотите иметь только записи (которые последние данные) и которые являются активными:

select t.* 
from companies t 
inner join (
    select max(id) as id 
    from companies 
    group by gid 
) last_entries 
on t.id = last_entries.id 
where t.status = 'Active'; 
+0

Большое спасибо. Это в основном работает. Он выбрасывал колонку с неизвестной ошибкой (столбец «статус»), поэтому я попытался изменить строку выбора, чтобы «выбрать статус, max (id) как id» ... Но, похоже, для каждой записи возвращается одна запись группа, активна ли последняя или нет ... (т. е. если я добавлю пятую строку с «5 Company1 Inactive», она все равно вернет строку) – user1182155

+0

Я исправил свой ответ. Это теперь эквивалентно таковому fthiella. –

2

Следующий запрос возвращает текущее состояние для каждой компании, используя трюк MySQL:

select gid, substring_index(group_concat(status order by id desc), ',', 1) as status 
from companies 
group by gid; 

Если вы хотите только те, которые в настоящее время активны:

select gid 
from companies 
group by gid 
having 'active' = substring_index(group_concat(status order by id desc), ',', 1) 
+0

Ницца; хотя я сомневаюсь, что он более эффективен, чем подзапрос, потому что СУБД необходимо выполнить поиск в конкатенированной строке. По крайней мере, с индексами на t.gid и t.active, подзапрос должен выиграть конкуренцию за производительность. (Кроме того, он более переносимый и, возможно, более читаемый/понятный). –

Смежные вопросы