在mysql中聚合结果时选择最新的字符串

时间:2009-10-28 05:51:32

标签: sql mysql greatest-n-per-group aggregation

我的任务是生成一些关于Request Tracker使用情况的报告。 Request Tracker是我工作的几个部门使用的票务系统。要做到这一点,我每晚都会将有关当天更改的票证的详细信息写入另一个数据库。这种方法将我的报告与RT使用的内部数据库模式分离。

在该报告的许多其他问题中,我需要报告每个部门每月解决的票数。在RT中,部门存储为CustomField,我的建模遵循这一趋势,您可以在下面的查询中看到。但是由于我每晚都会抓取快照,因此我会为票证设置多行,而且部门字段可能会在一个月内发生变化。我只对最近的部门领域感兴趣。我不知道如何在查询中得到它。

我知道我可以使用'GROUP BY'将我的查询结果减少到每张票一个,但是当我这样做时,我不知道如何获取最后一个部门设置。由于Departments都是字符串,MAX()不会得到最后一个。 MySQL不要求你为你选择的字段使用聚合函数,但结果是不确定的(从我的测试看起来它可能会抓住我的MySQL版本中的第一个)。

为了说明,这里是一个查询结果,显示了两张票,以及所有部门字段设置:

"ticket_num","date","QueueName","CF","CFValue","closed"
35750,"2009-09-22","IT_help","Department","",""
35750,"2009-09-23","IT_help","Department","",""
35750,"2009-09-24","IT_help","Department","",""
35750,"2009-09-25","IT_help","Department","",""
35750,"2009-09-26","IT_help","Department","",""
35750,"2009-10-02","IT_help","Department","",""
35750,"2009-10-03","IT_help","Department","",""
35750,"2009-10-12","IT_help","Department","",""
35750,"2009-10-13","IT_help","Department","",""
35750,"2009-10-26","IT_help","Department","Conference/Visitors","2009-10-26 10:10:32"
35750,"2009-10-27","IT_help","Department","Conference/Visitors","2009-10-26 10:10:32"
36354,"2009-10-20","IT_help","Department","",""
36354,"2009-10-21","IT_help","Department","",""
36354,"2009-10-22","IT_help","Department","FS Students",""
36354,"2009-10-23","IT_help","Department","FS Students",""
36354,"2009-10-26","IT_help","Department","FS Students","2009-10-26 12:23:00"
36354,"2009-10-27","IT_help","Department","FS Students","2009-10-26 12:23:00"

正如我们所看到的,这两张门票都在26日关闭,两张门票在第一次出现时都有一个空的部门字段。我在下面包含了我的查询,你可以看到我人为地限制了where语句后半部分返回的列数:

SELECT d.ticket_num, d.date, q.name as QueueName, cf.name as CF, cfv.value as CFValue, d.closed
FROM daysCF dcf
INNER JOIN daily_snapshots d on dcf.day_id = d.id
INNER JOIN Queues q on d.queue_id = q.id
INNER JOIN CustomFieldValues cfv on dcf.cfv_id = cfv.id
INNER JOIN CustomFields cf on cf.id = cfv.field_id
WHERE cf.name = 'Department' and (d.ticket_num = 35750 or d.ticket_num = 36354)
ORDER by d.ticket_num, d.date

如何修改该查询,以便我得到一个结果集,告诉我10月份“FS学生”关闭了一张门票,“会议/访客”关闭了一张门票?

2 个答案:

答案 0 :(得分:0)

Mysql没有LAST操作符,因此您确实需要使用临时表来执行此操作。

CREATE TEMPORARY TABLE last_dates SELECT ticket_num, MAX(date) AS date
  FROM daily_snapshots GROUP BY ticket_num

它会为您提供一张表格,其中包含每张票证的最后日期。然后在主查询中,使用ticket_num和date字段连接此表。这将过滤掉日期不是相应票号的最新行的所有行。

您可能需要该临时表的索引,我会留给您。

答案 1 :(得分:0)

这是Stack Overflow上频繁出现的“每组最大”问题。

以下是我在你的案例中解决它的方法:

SELECT d1.ticket_num, d1.date, q.name as QueueName, 
  cf.name as CF, cfv.value as CFValue, d1.closed
FROM daysCF dcf
INNER JOIN daily_snapshots d1 ON (dcf.day_id = d1.id)
INNER JOIN Queues q ON (d1.queue_id = q.id)
INNER JOIN CustomFieldValues cfv ON (dcf.cfv_id = cfv.id)
INNER JOIN CustomFields cf ON (cf.id = cfv.field_id)
LEFT OUTER JOIN daily_snapshots d2 ON (d1.ticket_num = d2.ticket_num AND d1.date < d2.date)
WHERE d2.id IS NULL AND cf.name = 'Department'
ORDER by d1.ticket_num, d1.date;