web-dev-qa-db-ja.com

SQLクエリでGroup by 1とGroup by 1,2,3を使用するのはなぜですか?

SQLクエリでは、Group by句を使用して集計関数を適用します。

  • しかし、Group by句で列名の代わりに数値を使用する背後にある目的は何ですか?例:1でグループ化。
28
ursitesion

これは実際にIMHOを行うには本当に悪いことであり、他のほとんどのデータベースプラットフォームではサポートされていません。

人々がそれをする理由:

  • 彼らは怠惰です-人々が多くを得るために余分な40ミリ秒を入力するのではなく簡潔なコードを書くことによって彼らの生産性が改善されると考える理由がわかりませんよりリテラルなコード。

それが悪い理由:

  • 自己文書化されていません-グループ化を理解するために、誰かがSELECTリストを解析する必要があります。これは実際にはSQL Serverでもう少し明確になります。SQLServerでは、MySQLのようなグループ化を知っているカウボーイをサポートしていません。

  • 脆弱です-ビジネスユーザーが別のレポート出力を望んでいたため、誰かが入ってSELECTリストを変更しましたが、今では出力が混乱しています。 GROUP BYで列名を使用した場合、SELECTリストの順序は関係ありません。

SQL ServerはORDER BY [ordinal]をサポートしています。ここでは、その使用に対するいくつかの平行した議論があります:

30
Aaron Bertrand

MySQLでは、エイリアスを使用してGROUP BYを実行できます( 列エイリアスの問題 )。これはGROUP BYを数値で処理するよりもはるかに優れています。

グーグルはそれを使用する多くの例を持っています、そしてなぜ多くがそれを使用しなくなったのですか.

正直なところ、私はORDER BYおよびGROUP BYの列番号を1996年以来使用していません(当時、私はOracle PL/SQL開発を行っていました)。カラム番号の使用は、実は昔からのものであり、下位互換性があるため、そのような開発者はMySQLやその他のRDBMSを引き続き使用できます。

9
RolandoMySQLDBA

以下のケースを検討してください:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Apps         |         1 |
| 2016-05-31 | Applications |         1 |
| 2016-05-31 | Applications |         1 |
| 2016-05-31 | Apps         |         1 |
| 2016-05-31 | Videos       |         1 |
| 2016-05-31 | Videos       |         1 |
| 2016-06-01 | Apps         |         3 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Videos       |         2 |
| 2016-06-01 | Apps         |         2 |
+------------+--------------+-----------+

アプリとアプリケーションを同じサービスと見なして、1日あたりのサービスごとのダウンロード数を調べる必要があります。 date, servicesでグループ化すると、AppsApplicationsは別々のサービスと見なされます。

その場合、クエリは次のようになります。

 select date, services, sum(downloads) as downloads
 from test.zvijay_test
 group by date,services

そして出力:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Apps         |         2 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Apps         |         5 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

しかし、アプリケーションとアプリケーションをグループ化することが要件であるため、これは必要なことではありません。では、何ができるでしょうか?

1つの方法は、Apps式またはApplications関数を使用してCASEIFに置き換え、サービス上で次のようにグループ化することです。

select 
  date,
  if(services='Apps','Applications',services) as services,
  sum(downloads) as downloads
from test.zvijay_test 
group by date,services

ただし、これは、AppsApplicationsを異なるサービスと見なしてサービスをグループ化し、以前と同じ出力を提供します。

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Applications |         5 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

列番号でグループ化すると、エイリアスされた列のデータをグループ化できます。

select
  date,
  if(services='Apps','Applications',services) as services,
  sum(downloads) as downloads
from test.zvijay_test
group by date,2;

したがって、次のように希望する出力が得られます。

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         4 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         9 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

これは、クエリを書くのに怠惰な方法であったり、エイリアスされた列をグループ化したりすることがMySQLでは機能しないことを何度も読みましたが、これはエイリアスされた列をグループ化する方法です。

これはクエリを作成する好ましい方法ではありません。エイリアスされた列をグループ化する必要がある場合にのみ使用してください。

8
imVJ

それを使用する正当な理由はありません。これは、ハードプレッシャーのある開発者が後でグループ化または並べ替えを理解するのを困難にする、または誰かが列の順序を変更したときにコードが無残に失敗することを可能にするように特別に設計された単に怠惰なショートカットです。仲間の開発者に配慮し、そうしないでください。

3
BriteSponge

これは私のために働いています。コードは、行を最大5つのグループにグループ化します。

SELECT
USR.UID,
USR.PROFILENAME,
(
    CASE 
    WHEN MOD(@curRow, 5) = 0 AND @curRow > 0 THEN
        @curRow := 0
    ELSE
        @curRow := @curRow + 1 
        /*@curRow := 1*/ /*AND @curCode := USR.UID*/
    END
) AS sort_by_total  
FROM
    SS_USR_USERS USR,
    (
        SELECT
            @curRow := 0,
            @curCode := ''
    ) rt
ORDER BY
    USR.PROFILENAME,
    USR.UID

結果は次のようになります

enter image description here

SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2;

SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2,3;

上記のクエリを検討してください:1でグループ化すると、最初の列でグループ化し、1,2でグループ化すると、最初と2番目の列でグループ化し、1,2,3でグループ化すると、最初の2番目と3番目の列でグループ化します。たとえば:

group by 1,2

この画像は、1,2でグループ化された最初の2つの列を示しています。つまり、カウントを見つけるためにdep_dateの異なる値を考慮していません(最初の2つの列のすべての異なる組み合わせを考慮に入れるためにカウントされます)。 group by 1,2,3

画像。ここでは、最初の3列すべてとカウントを見つけるために異なる値があります。つまり、最初の3列すべてでグループ化されています(カウントを計算するには、最初の3列のすべての異なる組み合わせが考慮されます)。

0
coder