2016-04-27 13 views
1

2人のユーザーのステータスイベントを含む次のような単純なテーブルを想定します。 status_idが1の場合、それらは「アクティブ」になり、それ以外の場合は非アクティブになります。 となったユーザーが、たとえば2015-05-01(その日付は含まれません)の1年以内に無効になったことを確認する必要があります。私は結果を得ることができますクエリMySQL:特定の日付の前に最新の日付でレコードを選択する方法

SELECT t1.* 
FROM user_status t1 
WHERE t1.date_assigned = (SELECT MIN(t2.date_assigned)  -- the first occurrence 
          FROM user_status t2 
          WHERE t2.user_id = t1.user_id  -- for this user 
          AND t2.status_id <> 1    -- where status not active 
          AND t2.date_assigned BETWEEN  -- within 1 yr of given date 
           '2015-05-01' + INTERVAL 1 DAY -- (not including that date) 
          AND 
           '2015-05-01' + INTERVAL 1 YEAR 
         ) 

を使用して

CREATE TABLE user_status(
     user_id INT, 
     status_id INT, 
     date_assigned VARCHAR(10)); 

INSERT INTO user_status(user_id, status_id, date_assigned) 
VALUES 
(1234, 1, '2015-01-01'), -- 1234 becomes active (status id = 1) 
(1234, 2, '2015-07-01'), -- 1234 de-activated for reason 2 

(5678, 1, '2015-02-01'), -- 5678 becomes active (status id = 1) 
(5678, 3, '2015-04-01'), -- 5678 de-activated for reason 3 
(5678, 5, '2015-06-01'); -- 5678 de-activated for reason 5 

user_id status_id date_assigned 
1234  2   2015-07-01 
5678  5   2015-06-01 

これは一種の権利であるが、ユーザ5678が存在してはならないので、彼らは内非アクティブなイベントがあったものの、希望の日付範囲が開始される前に既に無効になっていたため、はその範囲内で無効になるになりませんでした。

「アクティブなイベントがあるユーザを表示する」そのユーザの前のstatus_idが1だった、つまり非アクティブなときにアクティブだったユーザのみを表示する必要がありますイベントが発生しました。

誰でも私に正しい構文を教えてもらえますか?
あなたはあなたのクエリにNOT EXISTSを追加することができますSQL fiddle

答えて

1

を参照してください:

SELECT t1.* 
FROM user_status t1 
WHERE t1.date_assigned = (SELECT MIN(t2.date_assigned)  -- the first occurance 
          FROM user_status t2 
          WHERE t2.user_id = t1.user_id  -- for this user 
          AND t2.status_id <> 1    -- where status not active 
          AND t2.date_assigned BETWEEN  -- within 1 yr of given date 
           '2015-05-01' + INTERVAL 1 DAY -- (not including that date) 
          AND 
           '2015-05-01' + INTERVAL 1 YEAR 
         ) 
     AND NOT EXISTS (SELECT 1       -- such a record should not exist 
         FROM user_status t3 
         WHERE t3.user_id = t1.user_id -- for this user 
          AND t3.status_id <> 1  -- where status is not active 
          AND t3.date_assigned < -- before the examined period 
           '2015-05-01' + INTERVAL 1 DAY) 

Demo here

編集:

ます。また、複数を有する場合を考慮し、次のクエリを使用することができます開始日:

あなたの日付の基準内に見つける最小(ステータスが変更された最初の時間):
SELECT * 
FROM user_status 
WHERE (user_id, date_assigned) IN (
    -- get last de-activation date 
    SELECT t1.user_id, MAX(t1.date_assigned) 
    FROM user_status AS t1 
    JOIN (
    -- get last activation date 
    SELECT user_id, MAX(date_assigned) AS activation_date 
    FROM user_status 
    WHERE status_id = 1 
    GROUP BY user_id 
) AS t2 ON t1.user_id = t2.user_id AND t1.date_assigned > t2.activation_date 
    GROUP BY user_id 
    HAVING MAX(date_assigned) BETWEEN '2015-05-01' + INTERVAL 1 DAY AND '2015-05-01' + INTERVAL 1 YEAR AND 
     MIN(date_assigned) > '2015-05-01' + INTERVAL 1 DAY) 
+0

申し訳ありませんが、それは動作しません。別のレコード(5678、1、 '2015-04-20')を追加すると、5678が日付範囲の直前(以前は非アクティブになった後)に再度アクティブになるので、aのために非アクティブとしてピックアップされません2回目の2015年6月1日 – user3209752

+0

ああ、正しく動作するようです、ありがとうございます。私はあなたの答えを編集で受け入れました。 – user3209752

0

セルフソリューションに参加

select a.user_id,b.status_id,max(b.date_assigned) 
from user_status a 
inner join user_status b 
on a.user_id=b.user_id 
and a.date_assigned <b.date_assigned 
where b.status_id >1 and a.status_id=1 
group by a.user_id,b.status_id 
having max(b.date_assigned)> '2015-05-01' 
and max(b.date_assigned) <='2016-05-01' 
+0

Giorogosからの回答と同じ問題が残念です。別のレコードが追加されて、ユーザー5678が2015年04月20日(日付範囲の開始直前)に再びアクティブになると、2015-06-01で2回目の非アクティブ化として取得されますが、そのレコードを表示します。ちなみに、期間の開始日は実際のシステムのパラメータとして渡されるため、INTERVALを使用しますが、それはあなたのソリューションには影響しません。 – user3209752

+0

2つの余分なレコードを使って私のダミーテーブルに取り上げられます... – kostas

+0

それでも私はユーザー1234の記録だけでなく、5678も記録しています。 CREATE TABLE user_status( user_id INT、 status_id INT、 date_assigned VARCHAR(10)); (1234,2、 '2015-07-01)、1234がアクティブになります(ステータスID = 1) VALUES (1234、1、' 2015-01-01 ' (5678、1、 '2015-02-01')、 - 5678がアクティブになる(ステータスID = 1) (5678,3、 '2015-04 (5678、1、 '2015-04-20')、 - 5678アクティブもう一度 (5678,5、'2015-06-01 '); - 理由の理由で5678が非アクティブ5 – user3209752