1

我们使用自定义版本的 trac,人们可以根据两个标准为错误评分,让我们称它们为severityimportance

为简单起见,假设数据库包含以下表:

桌子ticket

id | title           | reporter
1  | SQL injection   | Torvalds
2  | Buffer Overflow | Linus
3  | Localization    | bofh

桌子votes

ticket_id | value | type       | voter
1         | 4     | severity   | Linus
1         | 2     | severity   | Torvalds
1         | 3     | severity   | bofh
1         | 4     | importance | Linus
1         | 3     | importance | Torvalds
2         | 4     | severity   | Linus
2         | 2     | severity   | Torvalds
2         | 1     | importance | Linus
2         | 1     | importance | bofh
3         | 1     | importance | Linus

因此,例如第一行意味着用户Linus建议将 4 作为工单 #1 的严重性分数。

现在,我在用于获取平均分数的 trac 报告中有以下 SQL 查询:

SELECT t.title, t.reporter, AVG(vs.value), AVG(vi.value), COUNT(vs.value), COUNT(vi.value)
FROM ticket t
LEFT JOIN votes vs ON vs.type = 'severity'   AND vs.ticket_id=t.id
LEFT JOIN votes vi ON vi.type = 'importance' AND vi.ticket_id=t.id;

在我的希望中,这应该返回一个具有以下值的表:

title | reporter | severity avg | importance avg | number of sev. votes | number of imp. votes
SQL injection | Torvalds | 3 | 3.5 | 3 | 2

从而告诉我有多少人投了票以及他们的票数是多少。

但是,由于工作方式LEFT JOIN,我得到的条目是严重性和重要性投票的笛卡尔积,所以平均值仍然有效,而两个计数都设置为 3x2=6 而不是正确的值。

有没有一种简单的方法来修复这个查询,以便它返回我想要的?

4

1 回答 1

2

将 CASE 语句与聚合函数结合起来:

SELECT 
  t.title, 
  t.reporter, 
  SUM(CASE WHEN v.type = 'importance' THEN 1 ELSE 0 END) AS Count_Imp,
  SUM(CASE WHEN v.type = 'severity' THEN 1 ELSE 0 END) AS Count_Sev,
  SUM(CASE WHEN v.type = 'importance' THEN v.value ELSE 0 END) / 
    Count_Imp AS Avg_Imp,
  SUM(CASE WHEN v.type = 'severity' THEN 1 ELSE 0 END) / 
    Count_Sev AS Avg_Sev
FROM 
  ticket t
  LEFT JOIN votes v 
  ON v.ticket_id = t.id;

如果 Trac SQL 不允许您重新使用别名Count_ImpCount_Sev您只需在平均计算列中重复这些语句。

于 2013-02-19T20:46:04.303 回答