2017-10-03 7 views
1

私はuserspaymentの2つのテーブルを持つデータベースを持っています。
各ユーザーには多くの支払いがあり、それぞれの支払いは成功または失敗できます。関連するテーブルの最後の4レコードを取得するMySQLクエリ

最後の4回の支払いに失敗したすべてのユーザーを取得するためのクエリを作成する必要があります。

これは私がこれまで試したものです:

select * 
from users u 
where u.id in(
    select p.user_id 
    from payments 
    where p.status = 'failed' 
    group by p.user_id 
    having count(p.id) = 4 
); 

しかし、あなたはこれが最後の4回の支払いをチェックするが、それらの全てだけでなく見ることができますように。したがって、4回の支払いに失敗したユーザーを返すことになります(過去4回だけでなく、グローバルでも)。

ことが重要であるが、テーブルのフィールドがある場合、私は知らない。

ユーザー:

id | name | email | password 

支払:

id | date | status      | user_id 
    |  | (can be success or failed) | (FK) 

更新:

これをsqlfiddleは私が必要とするものを理解するのに役立ちます。

クエリでは、支払いが4回失敗したすべてのユーザーが返されます。しかし、私は最新の4つの支払いが失敗したユーザーのみが必要です。この場合、IDのユーザーのみが表示されます5

+0

質問は少しあいまいです動作します。最後の4回の支払いが失敗したユーザー、または最後に4回の支払いが失敗したユーザーを希望しますか? –

+0

あなたのお返事ありがとう@Harshil。私はsqlfiddleを追加して、達成したいことを説明しようとしました。 –

答えて

1

これは

SELECT x.user_id, count(*) as cnt 
    FROM (
     SELECT a.user_id, a.date, a.status FROM payment AS a WHERE 
      (SELECT COUNT(*) FROM payment AS b 
      WHERE b.user_id = a.user_id AND b.date >= a.date) <= 4 
      ORDER BY a.user_id ASC, a.date DESC) AS x 
    WHERE x.status = 'failed' 
    GROUP BY x.user_id 
    HAVING cnt >=4; 
+0

ありがとう@ user8715013!私は解決策を見つけるために頭を打っていたが、これはちょうど完璧であり、非常にうまくいく(私の支払いテーブルには100万レコードが含まれており、あなたのクエリは5秒未満で実行される)。 –

0

ORIMERキーワードを使用してORDERを指定します。

あなたはWHERE文の中やろうとしているかわからない、完全にこの

select * 
from users u 
where u.id in(
    select p.user_id 
    from payments 
    where p.status = 'failed' 
    group by p.user_id 
    having count(p.id) = 4 
) ORDER BY p.id DESC LIMIT 4; 

試してみてください、しかしORDER BY p.id DESC LIMIT 4は4つの最も最近の行を取得します。

+0

はDESCであってはなりませんか? – isaace

+0

はい。ただ更新されました! –

0

私はあなたがこのようなクエリを使用することができると思う:あなたはその最後の4つの取引失敗したユーザーを、(最後の4,4を合計しない)場合

select users.id, users.name, users.email, users.password 
from users 
left join (
    select p1.id, p1.date, p1.status, p1.user_id,    
     count(p2.id) seq -- this count() creates a sequence number for each user ordered by date 
    from payment p1 
    left join payment p2 
     on p1.user_id = p2.user_id -- here I set sequence for each user 
    and p1.date <= p2.date   -- here I set sequence is ordered by data 
    group by p1.id, p1.date, p1.status, p1.user_id 
    ) t 
    on users.id = t.user_id 
where t.seq < 5 -- Now filter last 4 sequences of each user's payments 
    and t.status = 'failed' 
group by users.id, users.name, users.email, users.password 
having count(*) = 4; -- At last filter those have 4 failed in last 4 sequences 

[ SQL Fiddle Demo ]

1

次のクエリは、仕事を得る必要があります。

 select u.* from users u 
    where 
    id in 
    (select p.user_id from payment p 
    where (select count(*) from payment p1 
      where p.user_id = p1.user_id 
      and  p.date <= p1.date    
      order by p1.user_id asc,p1.date desc 
     ) <= 4 
    and p.status <> 'success' 
    group by p.user_id 
     having count(*)>=4); 

チェックsqlfiddle

希望すると助かります!

+0

お返事ありがとうございました。 2番目のケースです:最近4回の支払いが失敗したユーザーのリストを取得する必要があります。残念ながら、クエリはすべての支払い(最後の4件だけでなく)を考慮しているようです。私は[sqlfiddle](http://sqlfiddle.com/#!9/dfd1ba/1/0)のレコードをいくつか更新しました。例として –

+0

Okです。私に確認させてください –

+0

ちょっと、ちょっと!私はクエリとsqlfiddleリンクを更新しました。あなたはそれを試してみていただけますか? –

関連する問題