次のようなテーブルがあります。
+ ------ + -------- + ---------- + ------ + -------- + ------ -+ ------ + ------------ + | id |コード|カテゴリ| mq |体重|織り|ショー| min(price)| + ------ + -------- + ---------- + ------ + ----- --- + ------- + ------ + ------------ + | 1 | DT450R |カーボン| 1 | 450 |プレーン| 1 | 90 | | 2 | DT450R |カーボン| 2 | 450 |プレーン| 1 | 40 | | 3 | DT450R |カーボン| 5 | 450 |プレーン| 1 | 75 | | 7 | PP120Q |カーボン| 3 | 120 |ツイル| 1 | 28 | | 8 | PP120Q |カーボン| 7 | 120 |ツイル| 1 | 65 | | 9 | PP120Q |カーボン| 9 | 120 |ツイル| 1 | 49 | | 4 | ZX300R |カーボン| 1 | 300 |プレーン| 0 | 12 | | 5 | ZX300R |カーボン| 15 | 300 |プレーン| 1 | 128 | | 6 | ZX300R |カーボン| 30 | 300 |プレーン| 1 | 92 | + ------ + -------- + ---------- + ------ + -------- + ------- + ------ + ------------ +
ここに sqlfiddle を作成しました。
各コードの表から最小価格が必要です。次のクエリを使用してみました。
select id, code, category, mq, weight, weave, price, `show`, min(price) as total
from product group by code;
なぜグループは間違った結果を得るのですか? id = 1
の代わりに id =2
。
誤った出力:
+ ------ + -------- + ---------- + ------ + -------- + ------ -+ ------ + ------------ + | id |コード|カテゴリ| mq |体重|織り|ショー| min(price)| + ------ + -------- + ---------- + ------ + ----- --- + ------- + ------ + ------------ + | 1 | DT450R |カーボン| 1 | 450 |プレーン| 1 | 40 | | 7 | PP120Q |カーボン| 3 | 120 |ツイル| 1 | 28 | | 4 | ZX300R |カーボン| 1 | 300 |プレーン| 0 | 12 | + ------ + -------- + ---------- + ------ + -------- + ------- + ------ + ------------ +
期待される出力:
+ ------ + -------- + ---------- + ------ + -------- + ------ -+ ------ + ------------ + | id |コード|カテゴリ| mq |体重|織り|ショー| min(price)| + ------ + -------- + ---------- + ------ + ----- --- + ------- + ------ + ------------ + | 2 | DT450R |カーボン| 2 | 450 |プレーン| 1 | 40 | | 4 | ZX300R |カーボン| 1 | 300 |プレーン| 0 | 12 | | 7 | PP120Q |カーボン| 3 | 120 |ツイル| 1 | 28 | + ------ + -------- + ---------- + ------ + -------- + ------- + ------ + ------------ +
MySQL DBAとして、私は悲しいことにMySQLがそのSQL処理で (cavalier になる可能性があることを認めます。これの最も悪名高い偉業の1つはそのGROUP BY
動作。
例として、Aaron Bertrandが投稿に回答しました なぜSQLクエリでGroup by 1とGroup by 1,2,3を使用するのですか? ここで、MySQLのGROUP BY
なので cowboy who-knows-what-will-happen grouping
。 同意する必要がありました 。
GROUP BY
code
を使用
select code,min(price) as total
from product group by code
3つのことを行う
price
では、代わりにtotal
をエイリアスとして使用しますcode
とprice
の製品テーブルに再び結合します。ここに提案されたクエリがあります
select b.* from
(select code,min(price) as price from product group by code) a
inner join product b using (code,price);
または
select b.* from
(select code,min(price) as price from product group by code) a
inner join product b ON a.code=b.code AND a.price=b.price;
チェックアウト SQL Fiddle for this
特定のコードに対して同じ最低価格の行が複数存在する場合は、クエリを実行してサブクエリにし、結合して各(code
、price
)の最小IDを取得し、product
によってid
に結合します。 :
select bb.* from
(select a.code,a.price,min(b.id) id from
(select code,min(price) as price from product group by code) a
inner join product b using (code,price)
group by a.code,a.price) aa
inner join product bb using (id);
チェックアウト SQL Fiddle for that)
これでうまくいくはずです:
SELECT
p.*
FROM
product p
JOIN
(
SELECT
code, min(price) AS min_price
FROM
product
GROUP BY
code
) m ON p.code = m.code AND p.price = m.min_price
ORDER BY
p.id ;
注意:tiesがある場合(つまり、min(price)はグループごとに複数の行に表示されます)、すべての行が返されます。引き分けの場合に別の動作が必要な場合、状況は少し複雑になります... 2番目の選択肢の基準が必要です(可能であれば、別の引き分けを取得できない基準)、および別のレベルのsubquerying
。
このクエリも確認できます@ SQLFiddle
すべての@RolandoMySQLDBAの説明をチェックして、GROUP BY
mySQLで。それは簡単にトリッキーになる可能性があります。
質問は古いですが、さまざまなアプローチで回答が見つからなかったので、(結合を使用せずに)より簡単な代替案で応答することにしました。
グループ化により、GROUP BYステートメントに記録されたものと同じ値を持つレコードが統合されます。 MySQLがこれを行うとき、維持するレコードを選択します(非決定的)。彼が1つの行を保持し、他の行を破棄し、MIN命令の値を保持する、グループが完了するまで続ける、などを想像してください。
いくつかのテストでは、MariaDBが最後の行を保持しながら、MySQLは常に最初の行の値を選択しました。 doc にはこれへの参照はなく、サーバーが各グループの任意の値を自由に選択できることを示しているだけです。
これを解決するには、一時テーブル(またはサブクエリ)を作成し、保持されるレコード(上または下)とグループ化される列に従って、ASCまたはDESCのMINで使用される列を並べ替えます。次に、選択時に、MINコマンドでグループ化を使用します。
これを見てくださいフィドル。
CREATE TABLE product (`id` int, `code` varchar(6), `category` varchar(6), `mq` int, `weight` int, `weave` varchar(5), `price` int, `show` int);
INSERT INTO product
(`id`, `code`, `category`, `mq`, `weight`, `weave`, `price`, `show`)
VALUES
(1, 'DT450R', 'carbon', 1, 450, 'plain', 90, 1),
(2, 'DT450R', 'carbon', 2, 450, 'plain', 40, 1),
(3, 'DT450R', 'carbon', 5, 450, 'plain', 75, 1),
(4, 'ZX300R', 'carbon', 1, 300, 'plain', 12, 0),
(5, 'ZX300R', 'carbon', 15, 300, 'plain', 128, 1),
(6, 'ZX300R', 'carbon', 30, 300, 'plain', 92, 1),
(7, 'PP120Q', 'carbon', 3, 120, 'twill', 28, 1),
(8, 'PP120Q', 'carbon', 7, 120, 'twill', 65, 1),
(9, 'PP120Q', 'carbon', 9, 120, 'twill', 49, 1)
;
# RESOLUTION
# I have used non-temporary table due to the fiddle constraint.
CREATE table tbOrdened
select
id, `code`, category, mq, weight, weave, `show`, price
from product
order by price asc, `code`;
SELECT idforn, idativo, min(valor) AS valor from tbOrdened as tb1 GROUP BY idativo;