はじめに
第 4 回 ではカレンダービューの日付範囲クエリを解説しました。
本記事(第 5 回)では ガントチャート に絞り、GanttUtilities.Where() と GanttLimit の実装を解説します。
バージョン 1.5.2.0 を対象にしています
| 回 | タイトル |
|---|---|
| 第 1 回 | アーキテクチャ編 ── SQL を組み立てる仕組みの全体像 |
| 第 2 回 | 一覧編 ── フィルタとソートの WHERE・ORDER BY |
| 第 3 回 | 編集編 ── SELECT・INSERT・UPDATE の実装 |
| 第 4 回 | カレンダー編 ── 日付範囲クエリの実装 |
| 第 5 回(本記事) | ガントチャート編 ── GanttUtilities.Where() と GanttLimit |
| 第 6 回 | バーンダウンチャート編 ── 現在 + 履歴 UNION クエリ |
| 第 7 回 | 時系列チャート編 ── HorizontalAxis と NormalAndHistory |
| 第 8 回 | カンバン編 ── KambanLimit・全件取得・カード移動 |
| 第 9 回 | クロス集計編 ── GROUP BY と日付軸グループ化式 |
| 第 10 回 | 画像ライブラリ編 ── Binaries INNER JOIN クエリ |
| 第 11 回 | 分析チャート編 ── 分析パーツごとの現在+履歴 SQL |
処理フロー
GET /items/{siteId}/gantt
└─ IssueUtilities.Gantt() ← L9607 IssueUtilities.cs
├─ GanttDataRows() ← L9788 IssueUtilities.cs
│ └─ Rds.SelectIssues(進捗列多数,
│ WHERE: GanttUtilities.Where() + フィルタ)
│ ① SELECT(表示期間内レコード・COUNT SQL なし)
└─ dataRows.Count() <= Parameters.General.GanttLimit
件数チェック(SELECT COUNT は発行しない)
ガントチャートビューの SQL
GanttDataRows メソッド
ガントチャートのデータ取得は IssueUtilities.GanttDataRows() が担います。
private static EnumerableRowCollection<DataRow> GanttDataRows(
Context context, SiteSettings ss, View view, Column groupBy, Column sortBy)
{
// ① GanttUtilities.Where() を先に設定し、画面フィルタを追加
var where = view.Where(
context, ss,
where: Libraries.ViewModes.GanttUtilities.Where(context, ss));
// ② ガント期間パラメータの設定
var param = view.Param(context, ss);
var start = view.GanttStartDate.ToDateTime().ToUniversal(context);
var end = start.AddDays(view.GanttPeriod.ToInt()).AddMilliseconds(-3);
param.Add(new SqlParam() { VariableName = "Start", Value = start, NoCount = true });
param.Add(new SqlParam() { VariableName = "End", Value = end, NoCount = true });
// ③ SELECT(ガント表示に必要な列)
return Repository.ExecuteTable(context, statements: Rds.SelectIssues(
column: Rds.IssuesTitleColumn(context, ss)
.IssueId()
.WorkValue()
.StartTime()
.CompletionTime()
.ProgressRate()
.Status()
.Owner()
.Updator()
.CreatedTime()
.UpdatedTime()
.ItemTitle(ss.ReferenceType)
.Add(context, column: groupBy, function: Sqls.Functions.SingleColumn)
.Add(context, column: sortBy, function: Sqls.Functions.SingleColumn),
join: ss.Join(context, join: where),
where: where,
param: param))
.AsEnumerable();
}
ガントチャートの日付範囲条件
ガントチャートでは GanttUtilities.Where() で日付範囲条件が生成されます。カレンダーと同様の「3 パターン OR」が使われています。
WHERE (
"Issues"."StartTime" between @Start and @End
OR "Issues"."CompletionTime" between @Start and @End
OR "Issues"."StartTime" <= @Start AND "Issues"."CompletionTime" >= @End
)
AND ...(画面フィルタ条件・権限条件)
カレンダーとの違いは パラメータ名(Begin/End → Start/End)と、表示期間の計算方法 です。
GanttUtilities.Where() の実装
カレンダーの CalendarDataRows() が生列名を直接使うのに対し、GanttUtilities.Where() は Def.Sql.StartTimeColumn・CompletionTimeSql() という定義ファイル参照の SQL 式を使います。これはプリザンターが CompletionTime に「業務日換算」の補正を加えられる設計になっているためです。
public static SqlWhereCollection Where(Context context, SiteSettings ss)
{
// 3パターン OR:カレンダーと同じ構造
return Rds.IssuesWhere().Add(or: Rds.IssuesWhere()
// パターン①:期間全体を包む(StartTime <= @Start AND CompletionTime >= @End)
.Add(raw: "(({0}) <= @Start and {1} >= @End)".Params(
Def.Sql.StartTimeColumn,
CompletionTimeSql(context: context, ss: ss)))
// パターン②:開始日が期間内(StartTime between @Start and @End)
.Add(raw: "({0}) between @Start and @End".Params(
Def.Sql.StartTimeColumn))
// パターン③:終了日が期間内(CompletionTime between @Start and @End)
.Add(raw: "({0}) between @Start and @End".Params(
CompletionTimeSql(context: context, ss: ss))));
}
// CompletionTime に業務日換算の補正を加えた SQL 式を生成
private static string CompletionTimeSql(Context context, SiteSettings ss)
{
return Def.Sql.CompletionTimeColumn.Replace(
"#DifferenceOfDates#",
TimeExtensions.DifferenceOfDates(
ss.GetColumn(context: context, columnName: "CompletionTime")?
.EditorFormat, minus: true).ToString());
}
生成される WHERE 句のイメージ(業務日換算なしの場合):
WHERE (
"Issues"."StartTime" <= @Start AND "Issues"."CompletionTime" >= @End
OR "Issues"."StartTime" between @Start and @End
OR "Issues"."CompletionTime" between @Start and @End
)
AND ...(画面フィルタ・権限条件)
ガントチャートの表示期間
ガントチャートの表示期間は画面設定の GanttStartDate(開始日)と GanttPeriod(表示日数)から計算されます。
var start = view.GanttStartDate.ToDateTime().ToUniversal(context);
var end = start.AddDays(view.GanttPeriod.ToInt()).AddMilliseconds(-3);
AddMilliseconds(-3) は「最終日の 00:00:00 の直前まで」を表し、最終日そのものを取得対象に含めるための処理です。
ガントチャートの SELECT 句
カレンダーよりも多くの列を取得します。進捗バーの描画やアサイン表示に必要な情報が含まれます。
| 列 | 用途 |
|---|---|
IssueId |
一意識別子 |
WorkValue |
工数(バーの長さに使用) |
StartTime |
ガントバーの開始位置 |
CompletionTime |
ガントバーの終了位置 |
ProgressRate |
進捗率(バー内の塗りつぶし) |
Status |
ステータス色 |
Owner |
担当者表示 |
Updator |
更新者 |
CreatedTime / UpdatedTime
|
作成日時・更新日時 |
| グループ列 | グループ分けに使用 |
| ソート列 | グループ内のソートに使用 |
ORDER BY はカレンダーと同様に付与されません。ガントチャート上の配置はサーバー返却後にクライアント側で処理されます。
カレンダーとガントチャートの比較
| 項目 | カレンダー | ガントチャート |
|---|---|---|
| データ取得メソッド | CalendarDataRows() |
GanttDataRows() |
| 日付範囲パラメータ |
@Begin / @End
|
@Start / @End
|
| 日付範囲の種類 | 月 / 週 / 日 | 任意の開始日 + 表示日数 |
| FROM/TO 列 | 設定可能(TO は省略可) |
StartTime / CompletionTime 固定 |
| ORDER BY | なし(クライアントで処理) | なし(クライアントで処理) |
| 取得する主な列 | Id・Status・From・To・Title | Id・WorkValue・StartTime・CompletionTime・ProgressRate・Status |
まとめ
本記事では、ガントチャートの SQL を解説しました。
-
ガントチャート:
GanttDataRows()が同様の日付範囲条件を使い、進捗バー描画に必要な列(WorkValue・ProgressRate など)を取得する
第 6 回では、バーンダウンチャートの現在 + 履歴 UNION クエリを解説します。