MySQLのプロフェッショナルシリーズ - パート9:詳細グループ化されたクエリ、mysqlのグループは、ピットを持っています!

プレゼンテーションmysql5.7.25、CMDコマンド:環境。

この部分で

  1. クエリ構文をグループ化
  2. 集計関数
  3. 単一フィールドのグループ化
  4. マルチフィールドパケット
  5. パケット・フィルタ・データの
  6. データパケットをスクリーニングした後
  7. どこで差​​を有します
  8. パケットソート
  9. ここで、&グループ別&有する&ORDER BY&制限一起协作
  10. MySQLのパケットピット
  11. 複数列のクエリに使用します

クエリをグループ化

構文:

SELECT column, group_function,... FROM table
[WHERE condition]
GROUP BY group_by_expression
[HAVING group_condition];

説明:

group_function:集約関数。

group_by_expression:カンマで区切られた複数の、式をグループ化します。

group_condition:後にデータパケットをフィルタリングします。

パケットは、列の2種類があるだけでバックを選択します。

  1. 列によってグループに表示されます
  2. または重合列関数

集計関数

関数名 効果
最大 指定された列の最大値を照会
私に 問合せは、最小の列を指定します
カウント 統計クエリ結果の行数
合計、列戻り値の総和
平均 平均し、データの平均値は、指定された列を返します

パケットは、上記の関数を使用して、重合に使用することができます。

データを準備します

drop table if exists t_order;

-- 创建订单表
create table t_order(
  id int not null AUTO_INCREMENT COMMENT '订单id', user_id bigint not null comment '下单人id', user_name varchar(16) not null default '' comment '用户名', price decimal(10,2) not null default 0 comment '订单金额', the_year SMALLINT not null comment '订单创建年份', PRIMARY KEY (id) ) comment '订单表'; -- 插入数据 insert into t_order(user_id,user_name,price,the_year) values (1001,'路人甲Java',11.11,'2017'), (1001,'路人甲Java',22.22,'2018'), (1001,'路人甲Java',88.88,'2018'), (1002,'刘德华',33.33,'2018'), (1002,'刘德华',12.22,'2018'), (1002,'刘德华',16.66,'2018'), (1002,'刘德华',44.44,'2019'), (1003,'张学友',55.55,'2018'), (1003,'张学友',66.66,'2019');
mysql> select * from t_order;
+----+---------+---------------+-------+----------+
| id | user_id | user_name     | price | the_year |
+----+---------+---------------+-------+----------+
|  1 |    1001 | 路人甲Java    | 11.11 |     2017 |
|  2 | 1001 | 路人甲Java | 22.22 | 2018 | | 3 | 1001 | 路人甲Java | 88.88 | 2018 | | 4 | 1002 | 刘德华 | 33.33 | 2018 | | 5 | 1002 | 刘德华 | 12.22 | 2018 | | 6 | 1002 | 刘德华 | 16.66 | 2018 | | 7 | 1002 | 刘德华 | 44.44 | 2019 | | 8 | 1003 | 张学友 | 55.55 | 2018 | | 9 | 1003 | 张学友 | 66.66 | 2019 | +----+---------+---------------+-------+----------+ 9 rows in set (0.00 sec)

単一フィールドのグループ化

需要:単一のクエリの数、各ユーザのために出力:ユーザID、注文数、次のように

mysql> SELECT 
            user_id 用户id, COUNT(id) 下单数量
        FROM
            t_order
        GROUP BY user_id;
+----------+--------------+
| 用户id   | 下单数量     |
+----------+--------------+
|     1001 |            3 |
|     1002 |            4 |
|     1003 | 2 | +----------+--------------+ 3 rows in set (0.00 sec)

マルチフィールドパケット

需要:単一の番号の下に、年間利用者ごとのクエリ、出力フィールド:ユーザID、今年、注文数、次のように:

mysql> SELECT 
            user_id 用户id, the_year 年份, COUNT(id) 下单数量
        FROM
            t_order
        GROUP BY user_id , the_year;
+----------+--------+--------------+
| 用户id   | 年份   | 下单数量     |
+----------+--------+--------------+
|     1001 |   2017 |            1 |
|     1001 |   2018 | 2 | | 1002 | 2018 | 3 | | 1002 | 2019 | 1 | | 1003 | 2018 | 1 | | 1003 | 2019 | 1 | +----------+--------+--------------+ 6 rows in set (0.00 sec)

パケット・フィルタ・データの

キーワードの使用パケットのデータをフィルタリング

要件:以下のように、ユーザID、注文数:注文数、各ユーザのための2018年の出力をチェックする必要があります。

mysql> SELECT 
            user_id 用户id, COUNT(id) 下单数量
        FROM
            t_order t
        WHERE
            t.the_year = 2018
        GROUP BY user_id;
+----------+--------------+
| 用户id   | 下单数量     |
+----------+--------------+
|     1001 |            2 |
|     1002 |            3 | | 1003 | 1 | +----------+--------------+ 3 rows in set (0.00 sec)

データパケットをスクリーニングした後

データフィルタリングのグルーピング後、キーワードの使用を有します

要件:クエリ1よりも大きい注文ユーザ2018、出力:ユーザID、注文数、次のように

モード1:

mysql> SELECT
          user_id 用户id, COUNT(id) 下单数量
        FROM
          t_order t
        WHERE
          t.the_year = 2018
        GROUP BY user_id
        HAVING count(id)>=2; +----------+--------------+ | 用户id | 下单数量 | +----------+--------------+ | 1001 | 2 | | 1002 | 3 | +----------+--------------+ 2 rows in set (0.00 sec)

オプション2:

mysql> SELECT
          user_id 用户id, count(id) 下单数量
        FROM
          t_order t
        WHERE
          t.the_year = 2018
        GROUP BY user_id
        HAVING 下单数量>=2;
+----------+--------------+
| 用户id   | 下单数量     |
+----------+--------------+
|     1001 |            2 |
|     1002 | 3 | +----------+--------------+ 2 rows in set (0.00 sec)

どこで差​​を有します

どこのレコードは、グループ化(集約)スクリーニングの前にあり、かつ、パケットの終了後に審査結果を持って、最終的にはSQL全体にクエリ結果を返します。

これは、having句を含む、2つのクエリを有する、すなわち、SQLテーブルを取得し、クエリ結果を有する最初のクエリを含むものとして理解され、その後、結果テーブルに沿って選択された記録条件を使用し、これらのレコードを返すことができます機能を備えた後で重合し、そしてこの関数は必ずしも集計選択機能の背後にある同じ集合体ではないことができます。

パケットソート

要求は次のように、ユーザID、最大容量:各ユーザーの最大量を取得し、次いで逆、出力の最大量は、次のとおりです。

mysql> SELECT
          user_id 用户id, max(price) 最大金额
        FROM
          t_order t
        GROUP BY user_id
        ORDER BY 最大金额 desc;
+----------+--------------+
| 用户id   | 最大金额     |
+----------+--------------+
|     1001 |        88.88 |
|     1003 |        66.66 |
|     1002 | 44.44 | +----------+--------------+ 3 rows in set (0.00 sec)

ここで、&グループ別&有する&ORDER BY&制限一起协作

ここで、グループによって、これらのキーワードと共に使用した場合の限界によって、順序を有する、順序は次のように構文は、明確な限界を有します。

select 列 from 
表名
where [查询条件]
group by [分组表达式]
having [分组过滤条件]
order by [排序条件]
limit [offset,] count;

注意:

上記の記述された上記の順番で記述する必要があります。

例:

需要:次のように、ユーザID、注文数:注文の数、最後の記録物品、ショーの唯一の出力に応じて降順に、2以上の注文の数を2018チェックアウト:

mysql> SELECT
          user_id 用户id, COUNT(id) 下单数量
        FROM
          t_order t
        WHERE
          t.the_year = 2018
        GROUP BY user_id
        HAVING count(id)>=2 ORDER BY 下单数量 DESC LIMIT 1; +----------+--------------+ | 用户id | 下单数量 | +----------+--------------+ | 1002 | 3 | +----------+--------------+ 1 row in set (0.00 sec)

MySQLのパケットピット

そここの資料の冒頭には、選択欄の後者のグループは2種類を持つことができ、説明します。

  1. これは、列で後ろのグループに表示されます。
  2. 集約関数列

オラクル、SQLServerの、DB2は、この仕様書に従ってもあります。

本明細書中で使用されるバージョン5.7であるため、デフォルトでは、この仕様に来ています。

MySQLのいくつかの初期のバージョンでは、どのような要求せずに、あなたは法的列を持つバックを選択することができます。

デマンド:ユーザーID、最大量、年、次のように言葉で表現:シングルは最大ユーザーごとの額及び受注の年、出力を得ます:

mysql> select
          user_id 用户id, max(price) 最大金额, the_year 年份
        FROM t_order t
        GROUP BY t.user_id;
ERROR 1055 (42000): Expression #3 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'javacode2018.t.the_year' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

上記SQLエラー、その理由the_year上記2つのルールを満たしていないが(後者は集約関数を使用して、選択列またはグループに表示されなければならない)と述べたが、sql_mode限界このような規則は、我々が見sql_mode構成:

mysql> select @@sql_mode;
+-------------------------------------------------------------------------------------------------------------------------------------------+
| @@sql_mode                                                                                                                                |
+-------------------------------------------------------------------------------------------------------------------------------------------+
| ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+-------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

sql_modeのは含まれONLY_FULL_GROUP_BY、これは次の列は、上記の2点を選択の対象であることを示す基準を述べました。

することができますONLY_FULL_GROUP_BY削除、それは任意の列を選択し、後で追加することができ、我々は結果を見てください。

MySQLは変更しmy.iniたファイルを:

sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

次のようにmysqlの再起動して、もう一度実行して、効果は次のとおりです。

mysql> select
          user_id 用户id, max(price) 最大金额, the_year 年份
        FROM t_order t
        GROUP BY t.user_id;
+----------+--------------+--------+
| 用户id   | 最大金额     | 年份   |
+----------+--------------+--------+
|     1001 |        88.88 |   2017 |
|     1002 |        44.44 | 2018 | | 1003 | 66.66 | 2018 | +----------+--------------+--------+ 3 rows in set (0.03 sec)

上記のデータを見て、最初の88.88年は、2017私たちは生のデータを見てみましょう年:

mysql> select * from t_order;
+----+---------+---------------+-------+----------+
| id | user_id | user_name     | price | the_year |
+----+---------+---------------+-------+----------+
|  1 |    1001 | 路人甲Java    | 11.11 |     2017 |
|  2 | 1001 | 路人甲Java | 22.22 | 2018 | | 3 | 1001 | 路人甲Java | 88.88 | 2018 | | 4 | 1002 | 刘德华 | 33.33 | 2018 | | 5 | 1002 | 刘德华 | 12.22 | 2018 | | 6 | 1002 | 刘德华 | 16.66 | 2018 | | 7 | 1002 | 刘德华 | 44.44 | 2019 | | 8 | 1003 | 张学友 | 55.55 | 2018 | | 9 | 1003 | 张学友 | 66.66 | 2019 | +----+---------+---------------+-------+----------+ 9 rows in set (0.00 sec)

、比較のuser_id = 1001、価格= 88.88記事3つのデータ、すなわちthe_year 2018が、上記のパケットである2017の結果、私たちは期待矛盾した結果、仕様欄に、このようなmysqlのに従い、今回は接続しませんスクランブルは、MySQLが最初に取られます。

次のように正しい言葉遣いは、2つを提供しています:

mysql> SELECT
          user_id 用户id,
          price 最大金额,
          the_year 年份
        FROM
          t_order t1
        WHERE
          (t1.user_id , t1.price)
          IN
          (SELECT t.user_id, MAX(t.price) FROM t_order t GROUP BY t.user_id); +----------+--------------+--------+ | 用户id | 最大金额 | 年份 | +----------+--------------+--------+ | 1001 | 88.88 | 2018 | | 1002 | 44.44 | 2019 | | 1003 | 66.66 | 2019 | +----------+--------------+--------+ 3 rows in set (0.00 sec) mysql> SELECT user_id 用户id, price 最大金额, the_year 年份 FROM t_order t1,(SELECT t.user_id uid, MAX(t.price) pc FROM t_order t GROUP BY t.user_id) t2 WHERE t1.user_id = t2.uid AND t1.price = t2.pc; +----------+--------------+--------+ | 用户id | 最大金额 | 年份 | +----------+--------------+--------+ | 1001 | 88.88 | 2018 | | 1002 | 44.44 | 2019 | | 1003 | 66.66 | 2019 | +----------+--------------+--------+ 3 rows in set (0.00 sec)

書き込みの上記第一種、比較的稀であるが、inマルチフィールドクエリで使用されています。

推奨事項:後から機能によって使用されるか、またはグループで重合する必要があります発生を選択コラムを書くために、従う最高の標準仕様をクエリパケットを書きます。

概要

  1. 問い合わせパケットを書く、それが標準仕様に基づいて記述することが最善である、列が後に起こる選択する機能によって使用されるか、またはグループで重合する必要があります
  2. 構文の順序を選択:選択して、どこから、GROUP BY、持つ、制限によるため、順序はそれ以外の場合はエラー、間違っていることはできません。
  3. クエリを使用して複数の列に、あなたが行くように試みることができます
  4. https://www.cnblogs.com/itsoku123/p/11528107.html

おすすめ

転載: www.cnblogs.com/liliuguang/p/11531628.html