Максимальный групповой

У меня есть таблица, из которой я пытаюсь получить последнюю позицию для каждой безопасности:

Таблица:

Мой запрос для создания таблицы: SELECT id, security, buy_date FROM positions WHERE client_id = 4

+-------+----------+------------+
| id    | security | buy_date   |
+-------+----------+------------+
|    26 | PCS      | 2012-02-08 |
|    27 | PCS      | 2013-01-19 |
|    28 | RDN      | 2012-04-17 |
|    29 | RDN      | 2012-05-19 |
|    30 | RDN      | 2012-08-18 |
|    31 | RDN      | 2012-09-19 |
|    32 | HK       | 2012-09-25 |
|    33 | HK       | 2012-11-13 |
|    34 | HK       | 2013-01-19 |
|    35 | SGI      | 2013-01-17 |
|    36 | SGI      | 2013-02-16 |
| 18084 | KERX     | 2013-02-20 |
| 18249 | KERX     | 0000-00-00 |
+-------+----------+------------+

Я возился с версиями запросов на основе этой страницы, но я не могу получить результат, который я ищу.

Вот что я пытался:

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE buy_date = (SELECT MAX(t2.buy_date)
                    FROM positions t2
                    WHERE t1.security = t2.security)

Но это просто возвращает меня:

+-------+----------+------------+
| id    | security | buy_date   |
+-------+----------+------------+
|    27 | PCS      | 2013-01-19 |
+-------+----------+------------+

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

EDIT: Идентификатор позиции должен быть возвращен с максимальной датой покупки.

Ответ 1

Вы можете использовать этот запрос. Вы можете добиться результатов на 75% меньше времени. Я проверил с большим набором данных. Sub-Queries занимает больше времени.

SELECT p1.id, 
       p1.security, 
       p1.buy_date 
       FROM positions p1
left join
            positions p2
                on p1.security = p2.security
                   and p1.buy_date < p2.buy_date
      where 
      p2.id is null;

SQL-Fiddle ссылка

Ответ 2

Вы можете использовать подзапрос, чтобы получить результат:

SELECT p1.id, 
  p1.security, 
  p1.buy_date 
FROM positions p1
inner join
(
  SELECT MAX(buy_date) MaxDate, security
  FROM positions 
  group by security
) p2
  on p1.buy_date = p2.MaxDate
  and p1.security = p2.security

См. SQL Fiddle with Demo

Или вы можете использовать следующее с предложением WHERE:

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE buy_date = (SELECT MAX(t2.buy_date)
                  FROM positions t2
                  WHERE t1.security = t2.security
                  group by t2.security)

Смотрите скрипт SQL с демонстрацией

Ответ 3

Это делается с помощью простой группы. Вы хотите группировать по ценным бумагам и получать максимальную сумму buy_date. SQL:

SELECT security, max(buy_date) 
from positions
group by security

Обратите внимание, что это быстрее, чем bluefeet answer, но не отображает ID.

Ответ 4

В ответ на @bluefeet есть еще два способа получить желаемые результаты - и первый, вероятно, будет более эффективен, чем ваш запрос.

Я не понимаю, почему вы говорите, что ваш запрос не работает. Это выглядит очень хорошо и возвращает ожидаемый результат. Протестировано при SQL-Fiddle

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE buy_date = ( SELECT MAX(t2.buy_date)
                   FROM positions t2
                   WHERE t1.security = t2.security ) ;

Если проблемы возникают, когда вы добавляете условие client_id = 4, то это потому, что вы добавляете его только в одно предложение WHERE, пока вы должны добавить его в оба:

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE client_id = 4
  AND buy_date = ( SELECT MAX(t2.buy_date)
                   FROM positions t2
                   WHERE client_id = 4
                     AND t1.security = t2.security ) ;

Ответ 5

select security, max(buy_date) group by security from positions;

- все, что вам нужно, чтобы получить максимальную дату покупки для каждой безопасности (когда вы говорите вслух, что вы хотите от запроса, и вы включаете фразу "для каждого x", вы, вероятно, хотите, чтобы группа была на x)

Когда вы используете group by, все столбцы в выбранном элементе должны быть либо столбцами, которые были сгруппированы, либо агрегатами, поэтому, если, например, вы хотели включить идентификатор, вам, вероятно, придется использовать подобный подзапрос к тому, что у вас было до этого, так как, похоже, не существует какой-либо совокупности, которую вы можете разумно использовать в идентификаторах, а другая группа будет давать вам слишком много строк.