Группировка SQL по пониманию предложений (простой вопрос / SQL Server 2005) - PullRequest
2 голосов
/ 16 августа 2010

Привет всем, У меня возникли некоторые затруднения с пониманием причин группирования по SQL Server 2005.

У меня есть следующий запрос, который отлично работает и возвращает одну строку для каждого contact.id и 1-й случай события

SELECT
contact.id
,MIN(eve.date_created)
FROM _contact contact WITH(nolock)
INNER JOIN table2 tb2 WITH (nolock) ON contact.id = tb2.id1
INNER JOIN _event eve WITH (nolock) ON tb2.id2 = eve.id
INNER JOIN _cashtable cash WITH (nolock) ON cash.contact_id = contact.id
GROUP BY contact.id

Тем не менее, я ищу следующий запрос и по-прежнему извлекаю только одну строку для каждого contact.id

SELECT
contact.id
,MIN(eve.date_created)
,cash.id2    -- the cash linked to the first event
,eve.id      -- the first event linked to the contact    
FROM _contact contact with (nolock)
INNER JOIN _table2 tb2 WITH (nolock) ON contact.id = tb2.id1
INNER JOIN _event eve WITH (nolock) ON tb2.id2 = eve.id
INNER JOIN _cashtable cash WITH (nolock) ON cash.contact_id = contact.id
GROUP BY contact.id

Я получаю стандартное сообщение об ошибке, в котором говорится, что мне нужно добавить cash.id2 и eve.id в предложение group by, которое возвращает результаты, которые мне не нужны.

Я знаю, что есть потенциальные варианты использования rank () / разбиения или даже включая

select(MIN(eve.date_created) 

в предложении FROM, но я не уверен, что было бы лучше это поставить, и все еще не совсем понимаю, почему SQL требует, чтобы все было включено в оператор group by, и поэтому любой совет был бы хорош *

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 16 августа 2010

Я думаю, что вам нужен подзапрос, соединяющий таблицу событий с агрегацией, возвращающей только min (даты событий)

SELECT
contact.id,min_created,cash.id2    -- the cash linked to the first event
,eve.id      -- the first event linked to the contact    
FROM _contact contact 
INNER JOIN _table2 tb2  ON contact.id = tb2.id1
INNER JOIN _event eve  ON tb2.id2 = eve.id
inner join (select id, date_created as min_created from _event group by id) eve_min
on eve_min.id = eve.id and eve_min.min_created = eve.date_created 
INNER JOIN _cashtable cash  ON cash.contact_id = contact.id
0 голосов
/ 16 августа 2010

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

Полагаю, если вы сделаете что-то вроде

SELECT Contact.Id,
  MIN(eve.date_created),
  MAX(eve.date_created), //this will get you the range of events
  SUM(cash.id2), //total cash for all events
  MIN(eve.Id), //First event id
  MAX(eve.Id) //Latest event id
FROM _contact Contact //Etc. etc.

Ваш запрос будет работать для группировки. Однако то, на что вы хотите, похоже:

[Select your columns]
FROM _contact Contact 
INNER JOIN _Table2 tb2 on contact.id = tb2.id1 
  and tb2.id1 = (Select MIN(id2) from tb2 where tb2.id1 = contact.id)
INNER JOIN _event eve on tb2.Id2 = eve.id
INNER JOIN _cashtable cahs on cash.contact_id = contact.id
  and cash.id = (select MIN(id) from cash where cash.contact_id = contact.id)

YMMV, и ваша структура таблицы будет частично определять, насколько быстро она выполняется (то есть вы можете посмотреть на некоторые оптимизации). Кроме того, я сделал это полностью из памяти, поэтому вам, возможно, придется поиграть с этими INNER JOIN s, чтобы заставить их работать. Дело в том, что вы не пытаетесь захватить группу, вы пытаетесь захватить первый для каждого contact.id.

0 голосов
/ 16 августа 2010

Вы можете выбрать минимальный идентификатор как для события, так и для денег, который должен быть самым старым для каждого элемента, при условии, что в логике вставки и связывания для записей отсутствуют какие-либо странные изменения.Другой альтернативой является добавление предложений к объединениям, чтобы ограничить его первым или MIN ID, тогда вам не понадобится группировка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...