复杂的SQL查询,包括按组分组和将两行合并为一行。

3

好的,我需要帮忙。我通常很擅长SQL查询,但这个让我感到困惑。顺便说一下,这不是一项作业任务,而是Access数据库中的真实情况,下面是我自己编写的要求。


这是我的表格布局。如果有影响的话,它是在Access 2007中创建的;我正在使用SQL编写查询。

Id (primary key)
PersonID (foreign key)
EventDate
NumberOfCredits
SuperCredits (boolean)

人们会去参加各种活动,他们可以在某个活动中获得普通积分或超级积分,或者两者都有。如果某一行表示在该活动中获得的超级积分数量,则SuperCredits列为true,否则表示该行代表的是普通积分。

例如,如果有一个活动,174号参与,并在该活动中获得了3个普通积分和1个超级积分,则以下两行将添加到表中:

ID PersonID EventDate NumberOfCredits SuperCredits
1  174      1/1/2010  3               false
2  174      1/1/2010  1               true

有可能该人在活动中做了两件不同的事情,因此一个活动可能会有多于两列,可能会像这样:

ID PersonID EventDate NumberOfCredits SuperCredits
1  174      1/1/2010  1               false
2  174      1/1/2010  2               false
3  174      1/1/2010  1               true

现在我们想要打印一份报告。以下是报告的列:
PersonID
LastEventDate
NumberOfNormalCredits
NumberOfSuperCredits

报告将每个人的信息放在一行中。该行将显示此人参加的最新事件以及该事件中获得的普通和超级积分。
我要求您编写或帮助我编写SQL查询,以选择数据并进行GROUP BY和SUM()等操作。如果出于某种原因无法实现,请告诉我如何组织我的数据以使其成为可能。
这非常令人困惑,如果您不想费心解决它,我理解。我已尽力简化它,但如果您尝试并需要澄清,请随时提问。我将尝试弄清楚,但这超出了我的经验范围...
1个回答

3
创建一个查询/视图,内容如下(假设它叫PersonLastEvents):
select PersonId, max(EventDate) as LastEventDate
from Events
group by PersonId

您可以使用以下方式获取所需数据。我对Access不是很熟悉,因此您可能需要修改一些语法,但希望这能为您提供一种方法。

select l.PersonId, l.LastEventDate, 
  sum(case when e.SuperCredits = 'false' then e.NumberOfCredits end) 
    as NumberOfNormalCredits
  sum(case when e.SuperCredits = 'true' then e.NumberOfCredits end) 
    as NumberOfSuperCredits
from PersonLastEvents l
join Events e on l.PersonId = e.PersonId and l.LastEventDate = l.EventDate
group by l.PersonId, l.LastEventDate

顺便提一下,如果您将表格更改为具有两个数字列(NormalCredits,SuperCredits),可能会更容易实现所需的列求和,因为这样可以简单地使用sum()函数对列进行求和。


非常感谢,我永远不会想到这一点,但它完美地解决了问题!唯一需要更改的是Access没有case语句,而是使用switch(condition, value)。我希望有一种方法可以给你额外的声誉!! - Ricket
1
Access/Jet/ACE SQL不支持CASE语句,因此这个答案不可行。请不要使用未经测试的SQL方言回答与问题相关的数据库引擎。-1 - David-W-Fenton
如果只是布尔测试,CASE也可以被iif()替换。 - iDevlop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接