MySQLの機能が原因で、SQLでGROUPBYがどのように機能するかを誤解しています。標準SQLでは、SELECTステートメントのすべての非集計列はGROUP BY句に含まれている必要があります(値がすでにGROUP BY句にある列に100%依存している列には例外がありますが、この免除をサポートするSQLの種類はほとんどありません) 。
MySQLはデフォルトでこれを強制しませんが、これらの列にどの行の値が使用されるかは定義されていません。欲しいものを手に入れるかもしれませんが、そうでないかもしれません。そして、たとえあなたがそうしても、それは将来変わる可能性があります。
順序付けは通常、GROUP BYとは無関係ですが、ORDER句を指定しない場合、結果はGROUPingの実行に必要なものに基づいて順序付けられます(つまり、行を1つの順序で並べ替えてGROUP BYの場合、MySQLは、ORDER BY句で特に指示しない限り、後でレコードを並べ替えることはありません。
したがって、現在のデータでは、ads_post_idでグループ化すると、返されるidの値は22、23、24、104、250、253、または767になる可能性があります。MySQLがどちらを使用するかは定義されていません。
現在のデータを修正すると、MAX IDを取得できるため、これは簡単です。-
SELECT ads_post_id, MAX(id)
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
MAXは、グループ化された値ごとに1行を返します。
通常の問題は、その行に別の列が必要なことです。たとえば、サンプルデータの各行にもIPアドレスがあり、ads_post_idの最大IDに相当するものが必要だとします。-
id | ads_post_id ip_address
---------------------------------------------------------------------------
22 | 983314845117571 192.168.0.0
23 | 983314845117571 192.168.0.5
24 | 983314845117571 192.168.0.7
104 | 983314845117571 192.168.0.0
250 | 983314845117571 192.168.0.4
253 | 983314845117571 192.168.0.6
767 | 983314845117571 192.168.0.1
---------------------------------------------------------------------------
この場合、MAXだけを使用することはできません。たとえば、次のことを試した場合:-
SELECT ads_post_id, MAX(id), MAX(ip_address)
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
次のデータが返されます
id | ads_post_id ip_address
---------------------------------------------------------------------------
767 | 983314845117571 192.168.0.7
---------------------------------------------------------------------------
SQLのほとんどのフレーバーで次のことを試してみると、エラーが発生します。デフォルト設定のMySQLでは結果が得られますが、返されるIPアドレスは定義されていません(実際にはランダムです)。
SELECT ads_post_id, MAX(id), ip_address
FROM fb_ads
GROUP BY ads_post_id
LIMIT 6
これに対する解決策は、サブクエリで各ads_post_idの最大IDを取得し、それをテーブルに結合して残りの値を取得することです。-
SELECT a.ads_post_id,
a.id,
a.ip_address
FROM fb_ads a
INNER JOIN
(
SELECT ads_post_id, MAX(id) AS max_id
FROM fb_ads
GROUP BY ads_post_id
) sub0
ON a.ads_post_id = sub0.ads_post_id
AND a.id = sub0.max_id
別の方法は、GROUP_CONCAT集計関数を(ab)使用することです。 GROUP_CONCATは、連結されたすべての値を1つのフィールドに戻します。各フィールドは、(デフォルトでは)で区切られています。 ORDER BY句を追加して、連結される順序を強制することができます。 SUBSTRING_INDEXを使用して、最初のカンマまでのすべてを返すことができます。
これは単純なデータには役立ちますが、最大でNULLになるテキストデータまたはフィールドでは問題になります。
SELECT a.ads_post_id,
SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY id DESC), ',', 1),
SUBSTRING_INDEX(GROUP_CONCAT(ip_address ORDER BY id DESC), ',', 1)
FROM fb_ads
GROUP BY ads_post_id