3

问题:

我正在创建一个 Trac 报告,该报告显示我们图书馆每个章节的开发周期的每个阶段有多少票。一张票代表一项工作,通常是一个单独的例程。

例如,即将发布的版本(里程碑)有多少票处于第X章的同行评审阶段。

共有10个发展阶段和47个章节。

给定的 MySQL 查询针对所有 10 个开发阶段,但仅针对一章,有 25 行长,因此所有章节的整个查询超过 1200 行。

Trac 给出的错误是KeyError: 'numrows'查询变大的地方。

将查询直接输入 MySQL 时,给出的错误是Out of resources when opening file (Errcode: 24) (23)

问题

  • 重构 - 这可以做得“更好”的 sql 大师,有一些聪明的技巧/先进技术吗?

  • 方法 - 我是否需要完全不同的方法?

  • 配置 - MySQL 和/或 Trac 是否可以配置为接受非常大的查询

笔记:

表中的数据很小,当它在明显的大小限制下时,查询不会花费很长时间来执行。

查询从 Trac 系统传递到 MySQL,这对可以执行的操作设置了一些限制,例如只能从 trac 发送单个查询来生成报告。

可以在此处查看 Trac 报告的示例。

查询中的%c%*只是我在通过脚本生成查询时用于替换实际章节的唯一字符串。

SELECT '%c%' as Chapter,
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status IN ('new','assigned') ) AS 'New',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='document_interface' ) AS 'Document\
 Interface',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='interface_development' ) AS 'Inter\
face Development',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='interface_check' ) AS 'Interface C\
heck',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='document_routine' ) AS 'Document R\
outine',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='full_development' ) AS 'Full Devel\
opment',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='peer_review_1' ) AS 'Peer Review O\
ne',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%'AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='peer_review_2' ) AS 'Peer Review Tw\
o',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='qa' ) AS 'QA',
(SELECT count(ticket.id) AS Matches FROM engine.ticket INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%'AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='closed' ) AS 'Closed',
count(id) AS Total,
ticket.id AS _id
FROM engine.ticket
INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine'
4

5 回答 5

3

不要为每个计数创建一个子查询,而是使用 acase从已经为查询获取的数据中计数:

select '%c%' as Chapter,
  sum(case when ticket.status IN ('new','assigned') then 1 else 0 end) as 'New',
  sum(case when ticket.status='document_interface' then 1 else 0 end) as 'DocumentInterface',
  sum(case when ticket.status='interface_development' then 1 else 0 end) as 'Interface Development',
  sum(case when ticket.status='interface_check' then 1 else 0 end) as 'Interface Check',
  sum(case when ticket.status='document_routine' then 1 else 0 end) as 'Document Routine',
  sum(case when ticket.status='full_development' then 1 else 0 end) as 'Full Development',
  sum(case when ticket.status='peer_review_1' then 1 else 0 end) as 'Peer Review One',
  sum(case when ticket.status='peer_review_2' then 1 else 0 end) as 'Peer Review Two',
  sum(case when ticket.status='qa' then 1 else 0 end) as 'QA',
  sum(case when ticket.status='closed' then 1 else 0 end) as 'Closed',
  count(id) as Total,
  ticket.id as _id
from
  engine.ticket
  inner join engine.ticket_custom on ticket.id = ticket_custom.ticket
where
  ticket_custom.name='chapter' and
  ticket_custom.value LIKE '%c%' and
  type='New material' and
  milestone='1.1.12' and
  component NOT LIKE 'internal_engine'
于 2012-09-26T18:18:21.490 回答
2

不会完全重写它......但这是我的建议:

SELECT '%c%' as Chapter,
    SUM(CASE WHEN ticket.status IN ('new','assigned') THEN 1 ELSE 0 END) as `New`,
    ...
    SUM(CASE WHEN ticket.status='closed' THEN 1 ELSE 0 END) as 'Closed',
    count(id) AS Total,
    ticket.id AS _id
FROM engine.ticket
INNER JOIN engine.ticket_custom 
    ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' 
    AND ticket_custom.value LIKE '%c%' 
    AND type='New material' 
    AND milestone='1.1.12' 
    AND component NOT LIKE 'internal_engine'
GROUP BY ticket.id
;
于 2012-09-26T18:10:28.783 回答
1

当涉及到通过 Trac 生成这样的复杂报告时,最好根本不使用报告。报告对于相对简单的查询来说是可以的,但是当您组织许多不同的阶段和章节时,它们会变得笨拙。

相反,请尝试使用 wiki 页面创建您的“报告”。这将使您能够更好地控制布局和表示,而且您可以完全避免编写 SQL。以下是虚假报告的一些示例 wiki 代码,该报告显示所有未关闭的工单,按里程碑分组,然后按状态分组:

= Custom Report =
My custom report, as a wiki page

== Tickets for Milestone A ==
[[TicketQuery(milestone=MilestoneA,status!=closed,group=status,format=table)]]

== Tickets for Milestone B ==
[[TicketQuery(milestone=MilestoneB,status!=closed,group=status,format=table)]]

...

我不知道您是如何定义阶段和章节的,因此您需要调整查询参数以使用适当的工单字段。您还可以使用format其他选项来调整输出格式。

这只是一个简单的例子。该TicketQuery宏能够生成更复杂的报告。有关可能更接近(复杂性)您正在寻找的东西的示例,请查看Trac 项目的发行说明。整个“更改的详细列表”部分是使用单个TicketQuery宏生成的(点击“编辑”按钮以查看他们是如何做到的)。


另一个例子

要重新创建您链接到的图表,您可以执行以下操作:

||= **Id** =||= **Enhancements** =||= **Defects** =||= **Tasks** =||
||[milestone:v1.0 v1.0] || [[TicketQuery(milestone=v1.0,type=enhancement,format=count)]] || [[TicketQuery(milestone=v1.0,type=defect,format=count)]] || [[TicketQuery(milestone=v1.0,type=task,format=count)]] ||
... repeat for each milestone ...

本质上,format=count在宏中使用可以为您提供数据库为sum(case ...)Guffa 答案中的一条语句返回的内容。

使用宏而不是直接 SQL 这样做的最大好处是它变得与数据库无关。您不必担心数据库引擎(mysql、sqlite 等)之间的差异、Trac 数据库布局的变化、处理自定义字段的特殊代码等。

于 2012-09-26T20:42:52.873 回答
0

对,太丑了 您是否必须在一行中获取所有数据?这么多子查询将猛击服务器。你不能做一个标准的分组提取并在客户端做数据透视表吗?

例如

SELECT count(ticket.id) AS Matches, ticket_custom.name, ticket.status
FROM engine.ticket
INNER JOIN engine.ticket_custom ON ticket.id = ticket_custom.ticket
WHERE ticket_custom.name='chapter' AND ticket_custom.value LIKE '%c%' AND type='New material' AND milestone='1.1.12' AND component NOT LIKE 'internal_engine' AND ticket.status='qa' AND (ticket.status IN (........))
GROUP BY ticket.id, ticket_custom.name

然后,在伪代码中:

data = array()
while(row = fetch($result)) {
   data[ticket.id]][ticket.status] = row[ticket.status];
}

这样,您将只运行一个查询,并在 fetch 逻辑中做一些额外的小工作,以重新创建您的原始查询正在努力做的事情。

于 2012-09-26T18:06:24.637 回答
0

我最终在php. 这允许更大的灵活性来创建我需要的报告类型并且不涉及荒谬mysql queries的 . 将脚本与 trac 项目集成在一起,报告项目,即第XX章中QA 阶段的票证数量是 trac 中票证本身的超链接:http ://myhost.co.uk/trac-project/query?id=10&id =15。此外,NavAddPluggin允许自定义主 trac 导航栏,因此可以添加链接到脚本的菜单选项。

于 2012-10-03T15:13:46.740 回答