0

興味深い問題に遭遇しました。私は労働者のIDと彼らの訪問日の表を持っています。ここにダンプがあります:

CREATE TABLE `pp` (
  `id` int(11) DEFAULT '1',
  `day` int(11) DEFAULT '1',
  `key` varchar(45) NOT NULL,
 PRIMARY KEY (`key`)
) 

INSERT INTO `pp` VALUES 
   (1,1,'1'),
   (1,20,'2'),
   (1,50,'3'),
   (1,70,'4'),
   (2,1,'5'),
   (2,120,'6'),
   (2,90,'7'),
   (1,90,'8'),
   (2,100,'9');

したがって、少なくとも 1 回は 50 日以上欠勤した労働者を見つける必要があります。たとえば、ワーカーが 5 日目、95 日目、96 日目、97 日目に訪問した場合、デルタを見ると、最大のデルタ (90) が 50 を超えていることがわかるため、このワーカーを結果に含める必要があります。問題は、異なるワーカーの訪問間のデルタを効率的に見つけるにはどうすればよいかということです。

結果として得られるデータの配列として mysql テーブルを操作する方法を想像することさえできません。

したがって、さまざまなワーカーの日の値を分離し、並べ替えてから、それぞれの最大デルタを見つける必要があります。しかし、どのように?たとえば、並べ替えられた配列を sql で列挙する方法はありますか?

4

3 に答える 3

2

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

編集:

SELECT t.id, t.day1, t.day2 FROM (
  SELECT p1.id, p1.day day1, p2.day day2 FROM pp p1
    JOIN (SELECT * FROM pp ORDER BY day) p2
      ON p1.id = p2.id AND p1.day < p2.day
   GROUP BY p1.id, p1.day
  )  t
GROUP BY t.id
HAVING MAX(day2 - day1) >= 50
于 2012-11-28T08:42:24.937 に答える
1

これも解決策になる可能性があります。

select distinct pp.id
from pp
where pp.day-(select max(day)
              from pp pp2
              where
                pp2.id=pp.id and
                pp2.day<pp.day)>=50

(日はキー順ではないため、前のキーを検索するのではなく、現在の日の前の最大日を検索します)

于 2012-11-28T11:15:12.523 に答える
1

これは、私がそのような問題に対処するために使用した方法です。

SELECT distinct t3.id  FROM
(SELECT t1.id, t1.day, MIN(t2.day) nextday
FROM pp t1
JOIN pp t2 ON t1.id=t2.id AND t1.day<t2.day
GROUP BY t1.id, t1.day
HAVING nextday-t1.day >50) t3

(このバージョンを編集すると、わずかに改善されます) これにより、デルタが 50 を超えるすべての ID が検出されます。

動作を確認するには: SQL フィドル

最大デルタを見つけるには:

SELECT t3.id, MAX(t3.nextday-t3.day)  FROM
(SELECT t1.id, t1.day, MIN(t2.day) nextday
FROM pp t1
JOIN pp t2 ON t1.id=t2.id AND t1.day<t2.day
GROUP BY t1.id, t1.day) t3
GROUP BY t3.id

背後にあるロジックは、それが何を意味するにせよ、「次の」アイテムを見つけることです。これは順序付けられた属性であるため、次の項目は、調べた値よりも大きい値を持つ行の中で最も低い値を持つものとして定義できます...次に、「次の」値を元の値に結合し、デルタを計算します。該当するものだけを返します。他の列も必要な場合は、元のテーブルへの外部選択で JOIN を実行するだけです。

これがパフォーマンスに関して最善の解決策であるかどうかはわかりませんが、クエリをしばらく実行する余裕がある 1 回限りのレポートのクエリのみを作成しました。

ただし、発生する可能性のあるセマンティック エラーが 1 つあります。誰かが 1 日目、2 日目、3 日目に存在していたが、それ以降は存在しなかった場合、これは不在を検出しません。これを克服するためにUNION、すべての s の明日の日数を指定するテーブルに select を使用して特別な行を追加することができますがID、それはこのクエリを書き留めようとしないほど嫌なものになります...

于 2012-11-28T08:33:00.460 に答える