2015-03-26 1 views
0

ПОЖАЛУЙСТА, кто-нибудь поможет? Я вложил ЧАСЫ в эту глупую, глупую проблему. This stackoverview post ТОЧНО мой вопрос, и я пробовал ОБА предлагаемые решения бесполезны.Выберите максимальную дату путем группировки?

Вот мои особенности. Я извлек 4 записи из моей фактической базы данных, и не исключено, нет полей:

master_id date_sent type mailing response 
00001 2015-02-28 00:00:00 PHONE NULL NULL 
00001 2015-03-13 14:45:20 EMAIL ThankYou.html NULL 
00001 2015-03-13 14:34:43 EMAIL ThankYou.html NULL 
00001 2015-01-11 00:00:00 EMAIL KS_PREVIEW TRUE 
00001 2015-03-23 21:42:03 EMAIL MailChimp Update #2 NULL 

(жаль о выравнивании столбцов.)

Я хочу, чтобы получить самую последнюю рассылку и date_sent для каждого master_id. (Мой экстракт только один master_id, чтобы сделать этот пост просто.)

Так я запускаю этот запрос:

SELECT master_id,date_sent,mailing 
FROM contact_copy 
WHERE type="EMAIL" 

и получить ожидаемый результат:

master_id date_sent mailing   
1 3/13/2015 14:45:20 ThankYou.html  
1 3/13/2015 14:34:43 ThankYou.html  
1 1/11/2015 0:00:00 KS_PREVIEW  
1 3/23/2015 21:42:03 MailChimp Update #2 

НО, когда я добавляю это простое агрегирование, чтобы получить самую последнюю дату:

SELECT master_id,max(date_sent),mailing 
FROM contact_copy 
WHERE type="EMAIL" 
group BY master_id 
; 

я получаю неожиданный результат:

master_id max(date_sent) mailing 
00001 2015-03-23 21:42:03 ThankYou.html 

Итак, мой вопрос: почему он возвращает НЕПРАВИЛЬНОЕ ПОЧТОВАНИЕ?

Это делает меня орехами! Благодарю.

Кстати, я не разработчик, извините, если я нарушаю правило этикета, спрашиваю. :)

ответ

2

Это потому, что при использовании GROUP BY, все столбцы должны быть агрегатные столбцы, и рассылка не один из них ..

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

SELECT master_id,date_sent,mailing 
FROM contact_copy cc 
JOIN 
(SELECT master_id,max(date_sent) 
    FROM contact_copy 
    WHERE type="EMAIL" 
    group BY master_id 
) result 
ON cc.master_id= result.master_id AND cc.date_sent=result.date_sent 
+0

Hallelujah !! Спасибо! – SteveS

0

Вы получаете «неожиданный» результат из-за специфического расширения MySQL для функции GROUP BY. Результат, который вы получаете, на самом деле ожидается в соответствии с Справочным руководством по MySQL.

Ref: https://dev.mysql.com/doc/refman/5.5/en/group-by-handling.html


Другие СУБД отвергнет Ваш запрос как недействительный ... ошибка по линии «non-aggregate expressions included in the SELECT list not included in the GROUP BY»)

Мы можем получить MySQL, чтобы вести себя как другие базы данных. (и вернуть ошибку для этого запроса), если мы включили ONLY_FULL_GROUP_BY в режим SQL.

Ref: https://dev.mysql.com/doc/refman/5.5/en/sql-mode.html#sqlmode_only_full_group_by


Чтобы получить результат, который вы ищете ...

Если (master_id,type,date_sent) кортежа UNIQUE в contact_copy (то есть, если при заданных значениях master_id и type, там не будет «дублировать» значение date_sent), мы могли бы использовать операцию JOIN для получения заданного результата.

Во-первых, мы пишем запрос, чтобы получить «максимум» date_sent для заданных master_id и type. Например:

SELECT mc.master_id 
    , mc.type 
    , MAX(mc.date_sent) AS max_date_sent 
    FROM contact_copy mc 
WHERE mc.master_id = '0001' 
    AND mc.type = 'EMAIL' 

Чтобы получить всю строку, связанную с этим «максимальной» date_sent, мы можем использовать этот запрос как вложенное представление. То есть, обернуть текст запроса в круглых скобках, присвоить псевдоним, а затем ссылаться, что, как будто это таблица, например:

SELECT c.master_id 
    , c.date_sent 
    , c.mailing 
    FROM (SELECT mc.master_id 
       , mc.type 
       , MAX(mc.date_sent) AS max_date_sent 
      FROM contact_copy mc 
      WHERE mc.master_id = '0001' 
      AND mc.type = 'EMAIL' 
     ) m 
    JOIN contact_copy c 
    ON c.master_id = m.master_id 
    AND c.type  = m.type 
    AND c.date_sent = m.max_date_sent 

Обратите внимание, что если есть несколько строк, которые имеют то же значение master_id, type и date_sent, есть потенциал для возврата более чем одной строки. Вы можете добавить предложение LIMIT 1, чтобы гарантировать, что вы вернете только одну строку; какая из этих строк возвращается неопределенно, без предложения ORDER BY перед предложением LIMIT.