MySQLウィンドウ関数の具体的な使用法

MySQLウィンドウ関数の具体的な使用法

以前、MySQL で最熟悉的陌生人を見つけるためにファン向けにアンケートを実施しました~~MySQL のどの技術的なポイントがあなたにとって馴染みがあり、また馴染みのないポイントですか?

上位 3 つはほぼ予想どおりで、次のとおりです。

1. カーソル 2. ウィンドウ関数 3. クラスター化インデックス

これら3つのポイントは日常生活ではあまり使われませんが、面試中卻常被問到。多くの面接官は質問について漠然としか理解していないことに注意する価値があります。 。

今日はウィンドウ関数についてお話ししたいと思います。MySQL MySQL從8.0開始支持窗口函數。あなたの会社の MySQL バージョンではまだ満足できないかもしれませんが、ローカルで試してみることをお勧めします。本当に素晴らしいですよ!

ここに画像の説明を挿入

さて、前置きはこれくらいにして、いつものように前菜から始めて、今日のテスト テーブル データを見てみましょう。

この記事のデモンストレーションに使用されているテスト テーブルはchh_baozipuです。これは、陳哈哈の包子店を意味します。こっそり教えますが、ハ兄さんは今年饅頭屋をオープンしました。この表は過去6か月間の饅頭屋の利益を示しています~

mysql> chh_baozipu から * を選択します。
+----+--------------------+-------+---------+
| ID | 製品 | 売上 | 月 |
+----+--------------------+-------+---------+
| 1 | 豚肉とネギのパン | 600 | 2021-11 |
| 2 | 豚肉とネギのパン | 1600 | 2021-10 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 |
| 6 | 豚肉とネギのパン | 1000 | 2021-06 |
| 7 | 小麦パン | 700 | 2021-11 |
| 8 | 小麦パン | 200 | 2021-10 |
| 9 | 小麦パン | 300 | 2021-09 |
| 10 | 小麦パン | 0 | 2021-08 |
| 11 | 小麦パン | 100 | 2021-07 |
| 12 | 小麦パン | 200 | 2021-06 |
+----+--------------------+-------+---------+
セット内の行数は 12 です (0.00 秒)

なんと言えばいいでしょうか?いつか私の店に来てください。小麦を詰めたパンを皆さんにご馳走します。

1. ウィンドウ関数とは何ですか?

1. ウィンドウをどのように理解しますか?

実際、窗口の概念は非常に重要です。ウィンドウ関数を学習する場合、1 つのことだけを知っていて、もう 1 つを知らないというわけにはいきません。窗口が何を表しているかを理解し、いつ使用するかを把握する必要があります。

テストテーブルを例にして、包子鋪的豬肉大蔥包子這半年截至每月累計利潤統計を作成しましょう。

SELECT *,SUM(sales) over(ORDER BY `month`) as 累積利益 from chh_baozipu where product='豚肉とネギの饅頭';
mysql> SELECT *,SUM(sales) over(ORDER BY `month`) as 累積利益 from chh_baozipu where product='豚肉とネギの饅頭';
+----+--------------------+-------+---------+--------------+
| ID | 製品 | 売上 | 月 | 累計利益|
+----+--------------------+-------+---------+--------------+
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | 1000 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 2600 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 3400 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 4400 |
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | 6000 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 6600 |
+----+--------------------+-------+---------+--------------+
セット内の 6 行 (0.00 秒)

この SQL ステートメントから、id=6 の最初の行の窗口が最初の行であり、id=5 の 2 番目の行の窗口最初の 2 行である、などであることがわかります (下の図を参照)。

ここに画像の説明を挿入

窗口就是范圍的意思、レコード (行) の集合として理解できることがわかります。window 関数は滿足某種條件的記錄集合上執行計算特殊な関数です。

各レコードについて、このウィンドウ内で関数を実行する必要があります。一部の関数では、ウィンドウのサイズはレコードに応じて固定されており、靜態窗口です。逆に、一部の関数では、異なるレコードが異なるウィンドウに対応しています。この動的に変化するウィンドウは、滑動窗口と呼ばれます。この記事[dog head]を読めば、この文章をより深く理解できると思います。

2. ウィンドウ関数とは何ですか?

ウィンドウ関数はOLAP函數(Online Analytical Processing) とも呼ばれ、データのリアルタイム分析と処理を実行できます。

ウィンドウ関数はどのようなシナリオで主に使用されますか?主なカテゴリは 2 つあります。

  • ランキングの問題。例:饅頭屋の月間利益ランキングを確認する。
  • TOPN の質問、たとえば、各タイプのパンの利益が最も高い 2 か月を見つけます。

一般的なウィンドウ関数と集計関数は次のとおりです。

  • 特殊なウィンドウ関数: rank()dense_rank()row_number()
  • 集計関数: max()min()count()sum()avg()

集計関数はウィンドウ関数でも使用できるため、ウィンドウ関数と通常の集計関数は混同されやすいです。 両者の違いは次のとおりです。

  • 聚合函數多條記錄聚合為一條が、ウィンドウ関数は每條記錄都會執行,有幾條記錄執行完還是幾條
  • 集計関数はウィンドウ関数でも使用できます。例を挙げて説明します。

2. ウィンドウ関数の使用

基本的な構文:

<ウィンドウ関数> OVER (PARTITION BY <グループ化する列名> ORDER BY <並べ替える列名>);
-- over キーワードは、関数のウィンドウ範囲を指定するために使用されます。
--partition by はテーブルをグループ化するために使用されます。
-- order by 句は、グループ化された結果を並べ替えるために使用されます。

注: ウィンドウ関数は、where 句または group by 句の結果に対して二次的な操作を実行します。したがって、SQL 文の順序で実行されます。ウィンドウ関数は通常、select 句 (from 句の前) に配置されます。たとえば、前の SQL 文を上にドラッグして表示できます。

ウィンドウ関数とは何ですか?描くのが面倒なのでlulin916さんの地図をお借りします〜〜

ここに画像の説明を挿入

  • 順序関数: row_number() / rank() / dense_rank()
  • 分布関数: percent_rank() / cume_dist()
  • 関数の前後: lag() / lead()
  • 先頭と末尾の関数: first_val() / last_val()
  • その他の関数: nth_value() / nfile()

いくつかの例を見てみましょう:

1. 順序関数: row_number() / rank() / dense_rank()

ROW_NUMBER(): 順次ソート - 1、2、3

RANK(): 重複する数字をスキップして並列にソートします - 1、1、3

DENSE_RANK(): 重複する数字をスキップせずに並列ソート - 1、1、2

mysql> SELECT *,ROW_NUMBER() over(ORDER BY sales desc) as pro_ROW_NUMBER,rank() over(ORDER BY sales desc) as pro_rank,DENSE_RANK() over(ORDER BY sales desc) as pro_DENSE_RANK from chh_baozipu where product='Pork and Scallion Buns';
+----+--------------------+-------+---------+----------------+----------+----------------+
| id | 製品 | 売上 | 月 | pro_ROW_NUMBER | pro_rank | pro_DENSE_RANK |
+----+--------------------+-------+---------+----------------+----------+----------------+
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | 1 | 1 | 1 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 2 | 1 | 1 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 3 | 3 | 2 |
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | 4 | 3 | 2 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 5 | 5 | 3 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 6 | 6 | 4 |
+----+--------------------+-------+---------+----------------+----------+----------------+
セット内の 6 行 (0.00 秒)

上記の例からわかるように、3 つのウィンドウ関数は 3 つの異なる一般的なビジネス ニーズに対応しており、ソート統計を処理するには十分です。

今後、面接や筆記試験で学生に質問されたときは、自己クエリネストなどの低レベルのソリューションについて話さないでください。そうしないと、私のことを知っているとは言わないでください〜犬

2. 分布関数: percent_rank() / cume_dist()

この分配関数は基本的に使用されない関数なので、ここでは説明しません。興味のある学生は自分でBaiduで検索してみてください〜

3. 関数の前後: lag(expr,n) / lead(expr,n)

exprについては後で触れるので、統一的に説明しましょう。exprは表達式または列名になります。

before 関数と after 関数は、現在の行の前n行(LAG(expr,n))或后n行(LEAD(expr,n))の expr の値を返すためによく使用されます。

アプリケーションシナリオ: 上位n人の生徒のスコアと現在の生徒のスコアの差を照会する

内部 SQL は最初に LAG() 関数を使用して前の生徒のスコアを取得し、次に外部 SQL は現在の生徒と前の生徒のスコアを減算してスコアの差 diff を取得します。

ここで Ha Ge のテスト テーブルを使用するのは少し不便です。 。しかし、私の言っている意味は間違いなく分かるでしょう。確認してみましょう。

mysql> SELECT *,lag(sales,1) over win as pro_lag,lead(sales,1) over win as pro_lead from chh_baozipu WINDOW win as (PARTITION BY product ORDER BY sales desc);
+----+--------------------+--------+---------+----------+----------+
| id | 製品 | 売上 | 月 | pro_lag | pro_lead |
+----+--------------------+--------+---------+----------+----------+
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | NULL | 1600 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 1600 | 1000 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 1600 | 1000 |
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | 1000 | 800 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 1000 | 600 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 800 | NULL |
| 7 | 小麦パン | 700 | 2021-11 | NULL | 300 |
| 9 | 小麦パン | 300 | 2021-09 | 700 | 200 |
| 8 | 小麦パン | 200 | 2021-10 | 300 | 200 |
| 12 | 小麦パン | 200 | 2021-06 | 200 | 100 |
| 11 | 小麦パン | 100 | 2021-07 | 200 | 0 |
| 10 | 小麦パン | 0 | 2021-08 | 100 | NULL |
+----+--------------------+--------+---------+----------+----------+
セット内の行数は 12 です (0.00 秒)

ここで、この SQL が前の SQL と異なることに気づいたかどうかを学生に尋ねたいと思います。違いは何ですか?

*を選択、
lag(sales,1) は pro_lag として win を超えます。
pro_lead として、lead(sales,1) が wi​​n を上回る
chh_baozipu より、product='豚肉とネギのパン' 
WINDOW win as (PARTITION BY product ORDER BY sales desc);

1.把窗口提取出來設置了別名

実際、このメソッドはウィンドウを表示し、SQL を記述するときにエイリアスを使用するのと同じように、設置別名為:win 。これはよりシンプルで快適になりそうですか?

誰かがプログラマーに、どんなシンプルさが欲しいかと尋ねました。他の人があなたのコードを理解できなくても、それは素晴らしいと思うでしょう。このような学生は社会に打ち負かされたことがないのは明らかです。百年に一度現れる先祖の規範に遭遇すると、シンプルさが何であるかがわかります(Fat Brotherから画像を借りています)。

ここに画像の説明を挿入

2. ウィンドウにPARTITION BY productを追加しました

over 句のこのキーワードは、ウィンドウの内容を制御することを意味します。上記の基本構文では、over に 2 つのキーワードがあることを説明しました。

  • partition byウィンドウの内容をグループ化します。
  • order by 、グループ化後にウィンドウの内容を並べ替えます。

実は、ウィンドウの範囲を制御するもっと面白い方法があるんです~~

滑動窗口的范圍指定、行ベースと範囲ベースの 2 つの方法があります。ここでは、ウィンドウの範囲を制御するためによく使用される基于行に焦点を当てます。

BETWEEN frame_start AND frame_end 構文は通常、行の範囲を示すために使用されます。frame_start と frame_end は、異なる動的行レコードを識別するために次のキーワードをサポートできます。

  • 現在の行境界は現在の行であり、通常は他の範囲キーワードとともに使用されます。
  • 境界なし先行境界はパーティションの最初の行です
  • 境界はパーティションの最後の行です
  • expr PRECEDING 境界は現在の行からexprの値を引いた値です
  • expr FOLLOWING 境界は現在の行にexprの値を加えた値です

いくつかの例を見てみましょう。

①現在の行と前のn行(合計n+1行)の集計ウィンドウ関数を計算する

次の例では、コントロール ウィンドウのサイズは、現在の月の利益と過去 2 か月の利益の合計です。効果を見てみましょう。

SELECT *,SUM(sales) OVER win を「過去 3 か月の利益の合計」として選択します。
chh_baozipuより 
WINDOW win as (PARTITION BY product ORDER BY `month` ROWS 2 PRECEDING);
mysql> SELECT *,SUM(sales) OVER win を「過去3か月間の利益の合計」として選択します。
    -> chh_baozipu より 
	-> WINDOW win as (PARTITION BY product ORDER BY `month` ROWS 2 PRECEDING);
+----+--------------------+-------+---------+--------------------------+
| ID | 製品 | 売上 | 月 | 過去 3 か月の合計利益 |
+----+--------------------+-------+---------+--------------------------+
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | 1000 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 2600 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 3400 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 3400 |
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | 3400 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 3200 |
| 12 | 小麦パン | 200 | 2021-06 | 200 |
| 11 | 小麦パン | 100 | 2021-07 | 300 |
| 10 | 小麦パン | 0 | 2021-08 | 300 |
| 9 | 小麦パン | 300 | 2021-09 | 400 |
| 8 | 小麦パン | 200 | 2021-10 | 500 |
| 7 | 小麦パン | 700 | 2021-11 | 1200 |
+----+--------------------+-------+---------+--------------------------+
セット内の行数は 12 です (0.00 秒)

②現在の行、最初のn1行、最後のn2行の集計ウィンドウ関数を計算する

次の例では、コントロール ウィンドウのサイズは、現在の月の前月と翌月の利益の合計です。効果を見てみましょう。

SELECT *,SUM(sales) OVER win を「最初の 3 か月間の利益の合計」として選択します。 
chh_baozipuより 
WINDOW win as (PARTITION BY product ORDER BY `month` ROWS BETWEEN n1 PRECEDING AND n2 FOLLOWING);
mysql> SELECT *,SUM(sales) OVER win as '前月から翌月までの利益の合計' FROM chh_baozipu WINDOW win as (PARTITION BY product ORDER BY `month` ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING);
+----+--------------------+-------+---------+--------------------------+
| id | 製品 | 売上 | 月 | 前月から翌月までの利益の合計|
+----+--------------------+-------+---------+--------------------------+
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | 2600 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 3400 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 3400 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 3400 |
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | 3200 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 2200 |
| 12 | 小麦パン | 200 | 2021-06 | 300 |
| 11 | 小麦パン | 100 | 2021-07 | 300 |
| 10 | 小麦パン | 0 | 2021-08 | 400 |
| 9 | 小麦パン | 300 | 2021-09 | 500 |
| 8 | 小麦パン | 200 | 2021-10 | 1200 |
| 7 | 小麦パン | 700 | 2021-11 | 900 |
+----+--------------------+-------+---------+--------------------------+
セット内の行数は 12 です (0.00 秒)

4. 先頭関数と末尾関数: FIRST_VALUE(expr)、LAST_VALUE(expr)

head 関数と tail 関数は、expr の最初の値または最後の値を返すために使用されます。

アプリケーションシナリオ: 現在、日付の並べ替えによって當前最大月收入當前最小月收入を照会します。

*を選択、
FIRST_VALUE(売上)を「現在の最大月収」として勝ち越す、
LAST_VALUE(売上) を「現在の最低月収」として勝ち越す 
chh_baozipuより 
WINDOW win as (PARTITION BY product ORDER BY `month`);
mysql> SELECT *、FIRST_VALUE(sales) over win as '現在の最大月収'、LAST_VALUE(sales) over win as '現在の最小月収' from chh_baozipu WINDOW win as (PARTITION BY product ORDER BY `month`);
+----+--------------------+--------+---------+------------------------+------------------------+
| ID | 製品 | 売上 | 月 | 現在の最高月収 | 現在の最低月収 |
+----+--------------------+--------+---------+------------------------+------------------------+
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | 1000 | 1000 |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 1000 | 1600 |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 1000 | 800 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 1000 | 1000 |
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | 1000 | 1600 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 1000 | 600 |
| 12 | 小麦パン | 200 | 2021-06 | 200 | 200 |
| 11 | 小麦パン | 100 | 2021-07 | 200 | 100 |
| 10 | 小麦パン | 0 | 2021-08 | 200 | 0 |
| 9 | 小麦パン | 300 | 2021-09 | 200 | 300 |
| 8 | 小麦パン | 200 | 2021-10 | 200 | 200 |
| 7 | 小麦パン | 700 | 2021-11 | 200 | 700 |
+----+--------------------+--------+---------+------------------------+------------------------+
セット内の行数は 12 です (0.00 秒)

5. その他の関数: nth_value() / nfile()

nfile() は一般的に使用されないため、ここでは詳細には触れません。ここではNTH_VALUE(expr,n)関数についてのみ説明します。

NTH_VALUE 目的: ウィンドウ内の n 番目の expr の値を返します。

応用シナリオ:現在、陳哈哈饅頭店の月間利益ランキングの2位と3位の利益が表示されています。

*を選択、
nth_value(sales,2) が「現在2番目に高い月収」として勝ち越し、
nth_value(sales,3) が「現在月収第3位」として勝利 
chh_baozipuより 
WINDOW win as (PARTITION BY product ORDER BY `month`);
mysql> SELECT *,nth_value(sales,2) over win as '現在月収2位',nth_value(sales,3) over win as '現在月収3位' from chh_baozipu WINDOW win as (PARTITION BY product ORDER BY `month`);
+----+--------------------+-------+---------+--------------------------------+--------------------------------+
| id | 製品 | 売上 | 月 | 現在の月収第2位 | 現在の月収第3位 |
+----+--------------------+-------+---------+--------------------------------+--------------------------------+
| 6 | 豚肉とネギのパン | 1000 | 2021-06 | NULL | NULL |
| 5 | 豚肉とネギのパン | 1600 | 2021-07 | 1600 | NULL |
| 4 | 豚肉とネギのパン | 800 | 2021-08 | 1600 | 800 |
| 3 | 豚肉とネギのパン | 1000 | 2021-09 | 1600 | 800 |
| 2 | 豚肉とネギのパン | 1600 | 2021-10 | 1600 | 800 |
| 1 | 豚肉とネギのパン | 600 | 2021-11 | 1600 | 800 |
| 12 | 小麦パン | 200 | 2021-06 | NULL | NULL |
| 11 | 小麦パン | 100 | 2021-07 | 100 | NULL |
| 10 | 小麦パン | 0 | 2021-08 | 100 | 0 |
| 9 | 小麦パン | 300 | 2021-09 | 100 | 0 |
| 8 | 小麦パン | 200 | 2021-10 | 100 | 0 |
| 7 | 小麦パン | 700 | 2021-11 | 100 | 0 |
+----+--------------------+-------+---------+--------------------------------+--------------------------------+
セット内の行数は 12 です (0.00 秒)

章の要約

ウィンドウ関数について私が言いたいことはこれだけです。ウィンドウ関数は、MySQL 8 に触れてから私が発見した新しいものです。突然、MySQL 開発チームがまだ非常に創造的であると感じました。各バージョンでは、もちろん非常に実用的な新しい遊び方が追加されています。MySQL 9.0 が私たちにさらなる驚きをもたらしてくれることを期待しています。

MySQL ウィンドウ関数の具体的な使い方については、これで終わりです。MySQL ウィンドウ関数に関するより詳しい内容については、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Mysql8.0はソート問題を解決するためにウィンドウ関数を使用する
  • MySQL 8.0 ウィンドウ関数の紹介と概要
  • 効率的なページングクエリを実現するためのSQLウィンドウ関数のケース分析
  • SQLウィンドウ関数について簡単に学ぶ

<<:  Vue+ElementUI はページング関数を実装します - mysql データ

>>:  クラウドサーバーはBaotaを使用してPython環境を構築し、Djangoプログラムを実行します。

推薦する

さまざまなSQL結合を簡単に学ぶ

SQL JOIN 句は、テーブル間の共通フィールドに基づいて 2 つ以上のテーブルの行を結合するため...

Vue-Routerのインストールプロセスと原理の詳細

目次1. フロントエンドルーティングの実装原則2. vue-Routerの基本的な使い方2.1. イ...

登録ページを実装するためのJS、CSS、HTML

HTML と CSS で実装された登録ページ テンプレート。早速、コードを見てみましょう。更新: ...

ElementUI の el-dropdown に複数のパラメータを実装する方法

最近、業務上のボタンの増加により、ページレイアウトにボタンが多すぎて、ページが美しくなく、ユーザーエ...

CSS でデジタル ページング効果のコードと手順を実装する方法

かなりの数のウェブサイトがデジタルページング効果を使用しています。たとえば、このサイトのページングも...

js は、Element の入力コンポーネントのいくつかの機能を実装し、それをコンポーネントにカプセル化します (サンプルコード)

現在実装されているのは、基本的な使用方法、クリア可能なボックス、パスワードボックスです。参考リンク:...

CentOS7 から CentOS8 にアップグレードする方法 (詳細な手順)

この記事では、具体的な例を使用して、CentOS 7 から CentOS 8 にアップグレードする方...

js 正規表現の先読みと後読み、および非キャプチャグループ化

目次先読みと後読みをキャプチャグループと組み合わせる捕獲グループと非捕獲グループ前を向いて、後ろを振...

React で setInterval 関数を使用する例

この記事はWindows 10のシステム環境をベースに、Reactの学習と使用について説明しています...

AIX マウント NFS の書き込み効率が低い場合の解決策

NFSが提供するサービスマウント: サーバー上で /usr/sbin/rpc.mountd サーボ ...

DockerにNginxをインストールする方法

DockerにNginxをインストールするNginx は、IMAP/POP3/SMTP サービスも提...

MySQLの基本操作学習ノートテーブル

テーブルを作成テーブルテーブル名を作成create table if not exists 表名 m...

Vueはミックスインを使用してコンポーネントを最適化します

目次ミックスインの実装フック関数のマージプロジェクト実践伸ばす要約するVue は mixins AP...

フロートとBFCをクリアするCSSメソッド

イギリスBFC: ブロック書式設定コンテキストBFCレイアウトルール内箱は縦方向に次々に配置されます...

JSはプログレスバーのスムーズバージョンの詳細な計画を実装します

進捗バーがスムーズではないフロントエンドを学ぶ学生のほとんどは、オーディオプレーヤーやビデオプレーヤ...