web-dev-qa-db-ja.com

SQL:個別の行を選択しながら、1つのフィールドの最小値でグループ化

これが私がやろうとしていることです。このテーブルtがあるとしましょう:

id | record_date | other_cols
18 | 2011-04-03  | x
18 | 2012-05-19  | y
18 | 2012-08-09  | z
19 | 2009-06-01  | a
19 | 2011-04-03  | b
19 | 2011-10-25  | c
19 | 2012-08-09  | d

各IDについて、最小のrecord_dateを含む行を選択します。だから私は得るだろう:

id | record_date | other_cols
18 | 2011-04-03  | x
19 | 2009-06-01  | a

この問題について私が見た唯一の解決策は、すべてのrecord_dateエントリが異なることを前提としていますが、私のデータではそうではありません。 2つの条件でサブクエリと内部結合を使用すると、一部のIDに対して行が重複しますが、これは望ましくありません。

id | record_date | other_cols
18 | 2011-04-03  | x
19 | 2011-04-03  | b
19 | 2009-06-01  | a
54
user2765924

のようなものはどうですか

SELECT mt.*,     
FROM MyTable mt INNER JOIN
    (
        SELECT ID, MIN(Record_Date) MinDate
        FROM MyTable
        GROUP BY ID
    ) t ON mt.ID = t.ID AND mt.Record_Date = t.MinDate

これにより、IDごとの最小日付が取得され、それらの値に基づいて値が取得されます。重複するのは、同じIDに重複する最小record_datesがある場合のみです。

71
Adriaan Stander

mysql でこれを行うだけで、期待どおりの結果が得られます。

 SELECT id, min(record_date), other_cols 
  FROM mytable
  GROUP BY id

これはあなたのために働きますか?

12
Math

各カテゴリで最も安い製品を取得するには、次のように相関サブクエリでMIN()関数を使用します。

    SELECT categoryid,
       productid,
       productName,
       unitprice 
    FROM products a WHERE unitprice = (
                SELECT MIN(unitprice)
                FROM products b
                WHERE b.categoryid = a.categoryid)

外部クエリは、製品テーブル内のすべての行をスキャンし、相関サブクエリによって返される各カテゴリの最低価格と一致する単価を持つ製品を返します。

6
DIMI

firstアイテムは必要ないが、たとえばサブクエリでrownumberを使用して、結果セットのベースにすることができる2番目の番号を言う場合、ここで他の回答のいくつかに追加したいと思いますそれ。

SELECT * FROM
(
    SELECT
        ROW_NUM() OVER (PARTITION BY Id ORDER BY record_date, other_cols) as rownum,
        *
    FROM products P
) INNER
WHERE rownum = 2

これにより、サブクエリ内の複数の列を並べ替えることもできます。これは、2つのrecord_dateの値が同じ場合に役立ちます。必要に応じて、カンマで区切ることにより、複数の列を分割することもできます

1
Reese De Wind

これは単にそれを行います:

select t2.id,t2.record_date,t2.other_cols 
from (select ROW_NUMBER() over(partition by id order by record_date)as rownum,id,record_date,other_cols from MyTable)t2 
where t2.rownum = 1
1
jeff

以下のクエリは、各作業指示書の最初の日付を取得します(すべてのステータス変更を示すテーブル内):

SELECT
    WORKORDERNUM,
    MIN(DATE)
FROM
    WORKORDERS
WHERE
    DATE >= to_date('2015-01-01','YYYY-MM-DD')
GROUP BY
    WORKORDERNUM
0
SRVFan

これは古い質問ですが、これは誰かに役立ちます私の場合、私は大きなクエリを持っているので、サブクエリを使用できませんクエリ。私はMysqlを使用しています

select t.* 
    from (select m.*, @g := 0
        from MyTable m --here i have a big query
        order by id, record_date) t
    where (1 = case when @g = 0 or @g <> id then 1 else  0 end )
          and (@g := id) IS NOT NULL

基本的に、結果を順序付けしてから、各グループの最初のレコードのみを取得するために変数を配置しました。

0