SQL group by子句理解(简单问题/ SQL server 2005)

时间:2010-08-16 14:49:59

标签: sql sql-server sql-server-2005

全部, 我在使用sql server 2005中的聚合理解组背后的基本原理时遇到了一些困难。

我有以下查询工作正常,并为每个contact.id和事件的第一次出现返回一行

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

然而,我正在寻找的是拥有以下查询,并且每个联系人仍然只拉出一行.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()/ partitioning的潜在选项 甚至包括

select(MIN(eve.date_created) 

在FROM子句中,但我不确定哪个最好放这个,我仍然很困惑为什么SQL要求所有内容都包含在group by语句中,所以任何建议都会很棒:)

提前致谢!

3 个答案:

答案 0 :(得分:2)

我认为你需要一个子查询加入事件表,其自身聚合只返回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

答案 1 :(得分:0)

您可以为事件和现金选择最小ID,这应该是每个项目中最早的,假设条目的插入和链接逻辑没有任何奇怪的变化。

另一种方法是在连接中添加子句以将其限制为第一个或MIN ID,然后您不需要分组。

答案 2 :(得分:0)

您不需要将它们添加到group-by子句中,但您需要以某种方式聚合它们。 group-by子句的要点是您需要一组统计信息。也就是说,您想要同一个联系人ID的所有内容,而不仅仅是第一个记录。

我相信如果你做了像

这样的事情
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来让它们工作。这里的要点是,你不是想抓住小组,而是试图抓住每个contact.id的第一个小组。

相关问题