1

更新: 以下の Kordirko のソリューションは SQL Fiddle で機能しますが、私のコメントで述べたように、コードは自分の mysql db では機能しません。スキーマ コマンドを直接コピーし、フィドルからクエリのコピーを実行しました。私は両方をチェックしましたが、それらは同一のコードです。データベースとフィドルの間で同じ 5.1.61 mysql バージョンを確認しました。ライブ データベースでは、id 2 に対して 3 行が返され、フィドルでは 2 行のみが返されます (望ましい効果)。クエリを渡す前にフィドルがクエリを変更している可能性はありますか?

バックグラウンド:

スキャン結果の履歴として保持されているデータのテーブルがあります。通常、時間の経過に伴う結果の傾向をプロットするために使用されますが、別のことを試してみたいと思います。少なくとも 2 つのデータ ポイントがある場合は、最新のトレンドの上昇または下降 (パーセンテージ) を提供したいと考えています。より具体的には、トレンドの範囲をアクティブなプロジェクトに限定するために、これも最新の 7 日間に制限したいと思います。

テーブルは、プロジェクトが初めて実行されたとき、および issue_count が前回の実行から変更された場合にのみ更新されることに注意してください。

サンプル テーブル:

id  issues_count  updated
1   7922          2013-10-02 08:22:31
1   7981          2013-10-03 08:22:43
2   7754          2013-10-10 12:06:45
2   7922          2013-10-11 12:06:45
2   7981          2013-10-12 02:09:43
3   15536         2013-10-12 02:09:43
4   1233          2013-10-11 12:06:45
4   2493          2013-10-12 02:09:43
5   4349          2013-10-12 02:09:44

テーブル構造:

CREATE TABLE IF NOT EXISTS `issue_history` (
  `id` bigint(20) unsigned NOT NULL,
  `issues_count` mediumint(8) unsigned NOT NULL,
  `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  KEY `id_index` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=ascii;

結果のロジック:

上記のサンプルでは、​​両方の '1' id エントリを (今日から) 7 日以上経過しているため無視します。ID '3' と ID '5' については、データ ポイントが 1 つしかないため、何も返さないようにしたいと考えています。ID「2」と「4」の場合、タイムスタンプに基づいて最新のものとその直前のものを返したいと思います(それより前ではなく、最大2つ)。

結果の例:

2   7922          2013-10-11 12:06:45
2   7981          2013-10-12 02:09:43
4   1233          2013-10-11 12:06:45
4   2493          2013-10-12 02:09:43

他の考え:

順序はそれほど重要ではありませんが、最初に ID (asc または desc) でグループ化し、次に desc のタイムスタンプでグループ化することをお勧めします。

非効率的な試みを行う場合は、過去 24 時間のすべての ID を選択することでこれを処理できます。次に、これらの ID に一致するすべての行を選択し、タイムスタンプの desc で並べ替え、制限 2 にします。その後、私のコードはID ごとに 2 行未満の結果を削除する必要があります。おそらく、最初のものからサブクエリを選択し、2番目のものに埋め込むことを追求するでしょう。これは最善のアプローチではないと思いますが、機能するはずです。

私の懸念は、このテーブルが 1 日に数千行の割合で増加する可能性があることです。コマンドの実行にかかる時間を最小限に抑えたいと考えています。私は特に、プログラムから db を 2 回ヒットしたくありません。

4

1 に答える 1

2

このクエリを試してください:

SELECT id,
       issues_count,
       updated
FROM (
  SELECT sub1.*,
         IF(@last_id=sub1.id,(@rn:=@rn+1),(@rn:=1)) rn,
         (@last_id:=sub1.id) last_id
  FROM (
     SELECT ih.* 
     FROM issue_history ih
     JOIN (
       SELECT id
       FROM issue_history
        -- the most recent 7 days 
        WHERE updated > now() - interval 7 day
        GROUP BY id
        -- if there are at least 2 data points
        HAVING count(*) >= 2
     ) ih1
     ON ih.id = ih1.id AND ih.updated > now() - interval 7 day
     CROSS JOIN ( SELECT (@rn:=0),(@last_id=-12345)) init_variables
  ) sub1
  --  by id (asc or desc) and then by the timestamp in desc
  ORDER BY sub1.id ASC, sub1.updated DESC
) subquery
-- not any prior to that, 2 max
WHERE rn <= 2
ORDER BY id ASC, updated ASC

デモ ---> http://www.sqlfiddle.com/#!2/4309b/30


- - - - 編集 - - - - - -

ペアの最新の日付を決定し、この日付でレコードをソートする別のバージョン

SELECT id,
       issues_count,
       updated,
       most_recent_date
FROM (
  SELECT sub1.*,
         IF(@last_id=sub1.id,(@rn:=@rn+1),(@rn:=1)) rn,
         (@last_id:=sub1.id) last_id
  FROM (
     SELECT ih.*, ih1.most_recent_date
     FROM issue_history ih
     JOIN (
       -- max( updated ) --> most recent date
       SELECT id, max( updated ) most_recent_date
       FROM issue_history
        -- the most recent 7 days 
        WHERE updated > now() - interval 7 day
        GROUP BY id
        -- if there are at least 2 data points
        HAVING count(*) >= 2
     ) ih1
     ON ih.id = ih1.id AND ih.updated > now() - interval 7 day
     CROSS JOIN ( SELECT (@rn:=0),(@last_id=-12345)) init_variables
  ) sub1
  --  by id (asc or desc) and then by the timestamp in desc
  ORDER BY sub1.id ASC, sub1.updated DESC
) subquery
WHERE rn <= 2
ORDER BY most_recent_date, id, updated

デモ --> http://www.sqlfiddle.com/#!2/1eb9fe/1

于 2013-10-12T23:07:11.617 に答える