Personal tools
You are here: Home コラム 技術コラム sqliteがバックエンドの時のTracReportを書くtips
Document Actions

sqliteがバックエンドの時のTracReportを書くtips

sqliteがバックエンドの時のTracReportのSQLを書くtipsです。

主なテーブル構造(ticket)

CREATE TABLE ticket (
    id integer PRIMARY KEY,
    type text,
    time integer,
    changetime integer,
    component text,
    severity text,
    priority text,
    owner text,
    reporter text,
    cc text,
    version text,
    milestone text,
    status text,
    resolution text,
    summary text,
    description text,
    keywords text
);

CREATE TABLE ticket_custom (
    ticket integer,
    name text,
    value text,
    UNIQUE (ticket,name)
);

CREATE TABLE ticket_change (
    ticket integer,
    time integer,
    author text,
    field text,
    oldvalue text,
    newvalue text,
    UNIQUE (ticket,time,field)
);

ticketテーブルがticketの主テーブルです。ticket_customテーブルは、ticketごとに、カスタムフィールド名とその値のペアを記録します。カスタムフィールド数がmで、ticketの数がnの時、ticket_customテーブルのレコード数は m * n になります。ticket_changeテーブルはticketの更新履歴を記録します(この部分のテーブル設計はbugzillaと同じ)。

主なテーブル構造(subversion)

CREATE TABLE revision (
    rev text PRIMARY KEY,
    time integer,
    author text,
    message text
);

CREATE TABLE node_change (
    rev text,
    path text,
    node_type text,
    change_type text,
    base_path text,
    base_rev text,
    UNIQUE (rev,path,change_type)
);

revisionテーブルが、subversionの履歴を記録します。node_changeテーブルが履歴ごとの変更点を記録します(どのファイルが追加、削除されたかなど)。

文字列として入っているカラムを数値として比較

(おそらくsubversion以外にも対応できるために)、revisionテーブルのrevフィールドは、text型です。数値としてソートしたい場合、次のようにします。

SELECT * FROM revision ORDER BY rev+0;

ちなみに、sqliteは、カラムではなく値が型を持つという、RDB界のLispか、と突っ込みたくなるシステムです。テーブル定義のカラムについている型の意味は、 http://www.sqlite.org/datatype3.html を参照してください。

日付カラム(sqlite的には数値)を日単位で集計

ticketテーブルをtimeフィールドで日単位で集計するには次のようにします。

SELECT date(time,'unixepoch') AS Reported, count(*) AS Count
  FROM ticket 
  GROUP BY Reported
  ORDER BY time DESC

直近の128日だけを選択するには次のようにします。

SELECT date(time,'unixepoch') AS Reported, count(*) AS Count
  FROM ticket 
  WHERE time > strftime('%s','now','-128 day') 
  GROUP BY Reported
  ORDER BY time DESC

特定の期間だけを選択するには次のようにします(2007-01-01を2007-1-1と書くと動かないことに注意)。

SELECT date(time,'unixepoch') AS Reported, count(*) AS Count
  FROM ticket 
  WHERE time > strftime('%s','2007-01-01') AND time < strftime('%s','2007-12-31')
  GROUP BY Reported
  ORDER BY time DESC

月単位で集計するには次のようにします。

SELECT strftime('%Y/%m',time,'unixepoch') AS Reported, count(*) AS Count
  FROM ticket 
  GROUP BY Reported
  ORDER BY time DESC

カスタムフィールドとjoinするSQLの典型例

SELECT id AS ticket, summary (tcN.valueを書くとカスタムフィールドの値を表示)
    FROM ticket t
    LEFT OUTER JOIN ticket_custom tc1 ON tc1.ticket = t.id AND tc1.name = 'カスタムフィールド名'
    LEFT OUTER JOIN ticket_custom tc2 ON tc2.ticket = t.id AND tc2.name = 'カスタムフィールド名'
    WHERE tcN.valueを使った条件式 

ticketの統計情報

ticketの開発者ごとの更新数のランキングを出すには次のようにします。

SELECT author, count(*) AS count 
    FROM ticket_change 
    GROUP BY author 
    ORDER BY count DESC

開発者ごとのfixedにしたチケット数の集計(日単位)を出すには次のようにします。

SELECT date(time,'unixepoch') AS __group__, author, count(*) AS Count FROM ticket_change 
   WHERE field = 'resolution' AND newvalue = 'fixed' 
   GROUP BY __group__, author 
   ORDER BY __group__ DESC, Count DESC

開発者ごとのfixedにしたチケット数の集計(月単位)を出すには次のようにします。

SELECT strftime('%Y/%m',time,'unixepoch') AS __group__, author, count(*) AS Count FROM ticket_change 
   WHERE field = 'resolution' AND newvalue = 'fixed' 
   GROUP BY __group__, author 
   ORDER BY __group__ DESC, Count DESC

月ごとのオープンチケット数の増減を出すには次のようにします。

SELECT tm AS Month,sum(delta) AS Count
  FROM (SELECT id,strftime('%Y/%m',time,'unixepoch') tm,1 delta FROM ticket 
        UNION ALL 
        SELECT t.id id,strftime('%Y/%m',tc.time,'unixepoch') tm,(CASE tc.newvalue WHEN 'closed' THEN -1 ELSE 1 END) delta 
          FROM ticket t 
          JOIN ticket_change tc ON t.id=tc.ticket AND tc.field='status' AND (tc.newvalue='closed' or tc.oldvalue='closed')) 
  GROUP BY tm

月ごとのオープンチケット数の推移を出すには次のようにします(viewを使う場合)。viewを使わない場合、delta_viewの部分をそのままSELECTで置換してください。

CREATE VIEW delta_view AS 
  SELECT tm,sum(delta) delta_month 
    FROM (SELECT id,strftime('%Y/%m',time,'unixepoch') tm,1 delta FROM ticket 
          UNION ALL 
          SELECT t.id id,strftime('%Y/%m',tc.time,'unixepoch') tm,(CASE tc.newvalue WHEN 'closed' THEN -1 ELSE 1 END) delta 
            FROM ticket t 
            JOIN ticket_change tc ON t.id=tc.ticket AND tc.field='status' AND (tc.newvalue='closed' OR tc.oldvalue='closed'))
    GROUP BY tm;
SELECT a.tm,sum(b.delta_month) FROM delta_view a, delta_view b WHERE b.tm<=a.tm GROUP BY a.tm;

subversionの統計情報

subversionの開発者ごとのコミット数のランキングを出すには次のようにします。

SELECT author,count(*) count 
    FROM revision 
    GROUP BY author 
    ORDER BY count DESC

月ごとの変更ファイル数合計は次のようにします。

SELECT strftime('%Y/%m',revision.time,'unixepoch') month, count(*) 
    FROM revision
    LEFT OUTER JOIN node_change ON revision.rev = node_change.rev 
    GROUP BY month

最近1ヶ月でファイルごとのコミット回数の統計は次のようにします。

SELECT node_change.path path, count(*) count 
    FROM revision 
    LEFT OUTER JOIN node_change ON revision.rev = node_change.rev 
    WHERE revision.time > strftime('%s','now','-30 day') 
    GROUP BY path 
    ORDER BY count DESC

最近一ヶ月で修正が多いファイルのランキングを出すには次のようにします。

SELECT node_change.path path, count(*) count 
    FROM revision 
    LEFT OUTER JOIN node_change ON revision.rev = node_change.rev 
    WHERE node_change.node_type = 'F' AND revision.time > strftime('%s','now','-30 day')
    GROUP BY path 
    ORDER BY count DESC

tracの特殊な別名

普通のSQLの場合、ASでつけた別名は、結果セットの参照方法を変えるだけです。tracはいくつかの定義済みの別名を付けることで表示HTMLに影響を与えることができます。

  • id AS ticket ...チケットIDをticketという別名にすることで、結果の各行が、該当チケットへのHTMLリンクになります
  • foo AS __group__ ...結果のfooカラムの値ごとにHTMLがグループ化されます。言葉では分かりにくいのでやってみてください

Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.