sql >> データベース >  >> RDS >> Mysql

MYSQL-DESCの順序でIDで並べ替え、Xでグループ化

    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 
    


    1. selectを続編し、別のテーブルエイリアスを含めます

    2. PayPalODBCドライバー

    3. mysqldbを使用してRailsでサーバーを起動できません

    4. OracleのLOCALTIMESTAMP()関数