

SQL文を教えて下さい。  
user_id 毎の最新の bills 一覧を得る SELECT 文はどう書けば良いのでしょうか？

## テーブル定義

[code]

    mysql> desc bills;
    +---------------------+--------------+------+-----+---------+----------------+
    | Field               | Type         | Null | Key | Default | Extra          |
    +---------------------+--------------+------+-----+---------+----------------+
    | id                  | int(11)      | NO   | PRI | NULL    | auto_increment |
    | user_id             | int(11)      | YES  | MUL | NULL    |                |
    | created_at          | datetime     | YES  |     | NULL    |                |
    +---------------------+--------------+------+-----+---------+----------------+
    
[/code]

## サンプル

[code]

    +----+---------+------------+
    | id | user_id | created_at |
    +----+---------+------------+
    |  1 |     111 | 2015-01-01 |
    +----+---------+------------+
    |  2 |     111 | 2015-01-02 |
    +----+---------+------------+
    |  3 |     111 | 2015-01-03 | ← 111 の中で最新の日付
    +----+---------+------------+
    |  4 |     222 | 2015-01-02 | ← 222 の中で最新の日付
    +----+---------+------------+
    |  5 |     222 | 2015-01-01 |
    +----+---------+------------+
    
[/code]

## 期待する結果

[code]

    +----+---------+------------+
    | id | user_id | created_at |
    +----+---------+------------+
    |  3 |     111 | 2015-01-03 |
    +----+---------+------------+
    |  4 |     222 | 2015-01-02 |
    +----+---------+------------+
    
[/code]


CC BY-SA 3.0
2015-09-15T02:31:52.160
16616
2019-06-19T08:18:43.860
7208
question
mysql sql
指定したカラム毎で最新のリストが欲しい(SQL, SELECT文)


結合し直してどの行が該当したのかを探すことでしょうか。

[code]

    SELECT bills.*
    FROM bills
    INNER JOIN (SELECT user_id, MAX(created_at) AS created_at
                FROM bills
                GROUP BY user_id) AS max
    ON bills.user_id = max.user_id AND bills.created_at = max.created_at
    
[/code]

このクエリからわかりますが、あくまで`user_id`毎に`created_at`の最大値を選んだだけですので、最大値が複数行存在した場合は結果も複数になります。  
それでは困るという場合は再度グループ化し、どのような`id`を選択するかを考える必要があります。


CC BY-SA 3.0
2015-09-15T03:00:21.443
16618
2015-09-15T03:00:21.443
4236
16616
answer


既に回答は出されていますが、別の方法でやってみます。

[code]

    SELECT * FROM bills AS b WHERE created_at = (
      SELECT MAX(created_at) FROM bills AS bs WHERE b.user_id = bs.user_id
    );
    
[/code]

この場合も最大値を持つレコードが複数ある場合は全て選択されることになります。

**追記**

最大値を持つレコードが複数ある場合に、例えば `id` が最も大きいレコードを抽出するには以下の様にします。

[code]

    SELECT * FROM bills AS b WHERE id = (
      SELECT MAX(id) FROM bills AS bs
      WHERE b.user_id = bs.user_id AND
            created_at = (
              SELECT MAX(created_at) FROM bills AS bs
              WHERE b.user_id = bs.user_id)) ORDER BY user_id;
    
[/code]

最小値の `id` を持つレコードを抽出する場合は、上記の `MAX(id)` を `MIN(id)` に変更します。


CC BY-SA 3.0
2015-09-15T03:52:50.710
16620
2015-09-15T05:17:47.820
2015-09-15T05:17:47.820
16616
answer


id 列が不要ならば、以下のSQLで取得できます。

[code]

    SELECT user_id, MAX(created_at) FROM bills GROUP BY user_id
    
[/code]


CC BY-SA 4.0
2019-06-19T08:18:43.860
55917
2019-06-19T08:18:43.860
14334
16616
answer