Open36

MySQLとお近づきになるための第一歩

0Yu0Yu

データベースにログインする

$ mysql -h host -u user -p menagerie データベース名  
Enter password: ********  

※menagerieはパスワードではないことに注意。コマンド行で -p オプションのあとにパスワードを入力する場合は、間にスペースを入れずに入力する (たとえば、-p mypassword ではなく、-pmypassword)。

0Yu0Yu

テーブルから情報を取り出したい

mysql> SELECT 何のカラムリストを
FROM どのテーブルから
WHERE オプションを記述(取得対象となる行の条件を 1 つまたは複数);
mysql> SELECT * FROM テーブル名;

でテーブル全体を取り出す

0Yu0Yu

テーブルから特定の行だけを取り出す

以下は任意のテーブル(pet)からnameのカラムを検査し、Bowserのレコードを選択する例

mysql> SELECT * FROM pet WHERE name = 'Bowser';
+--------+-------+---------+------+------------+------------+
| name   | owner | species | sex  | birth      | death      |
+--------+-------+---------+------+------------+------------+
| Bowser | Diane | dog     | m    | 1989-08-31 | 1995-07-29 |
+--------+-------+---------+------+------------+------------+

https://dev.mysql.com/doc/refman/5.6/ja/selecting-rows.html

0Yu0Yu

テーブルからカラム一覧を取得したい

mysql> DESCRIBE テーブル名;

or

mysql> SHOW COLUMNS FROM テーブル名;
0Yu0Yu

カラム名の一覧を調べる方法

mysql>SHOW COLUMNS FROM テーブル名;

Cityテーブルのカラムの情報を取得したいとき

mysql> SHOW COLUMNS FROM City;
+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| Id         | int(11)  | NO   | PRI | NULL    | auto_increment |
| Name       | char(35) | NO   |     |         |                |
| Country    | char(3)  | NO   | UNI |         |                |
| District   | char(20) | YES  | MUL |         |                |
| Population | int(11)  | NO   |     | 0       |                |
+------------+----------+------+-----+---------+----------------+
5 rows in set (0.00 sec)
  • Fieldがカラム名
  • Typeがカラムデータ型
  • Collationはバイナリ以外の文字列カラムの場合は照合順序、その他のカラムの場合は NULL を示します。この値は、FULL キーワードを使用した場合にのみ表示されます。
  • Null フィールドには、このカラムに NULL 値を格納できる場合は YES、できない場合は NO が含まれます。
  • Key フィールドは、このカラムがインデックス設定されているかどうかを示します。

https://dev.mysql.com/doc/refman/5.6/ja/show-columns.html

0Yu0Yu

実行中のクエリの確認

show processlist;
0Yu0Yu

LIMIT句

LIMIT 行数で取得するデータの行数の上限を設定する
メモリ不足したときなどに確認用で使った
以下は使用例

mysql> SELECT * FROM ratings ORDER BY category LIMIT 5;
+----+----------+--------+
| id | category | rating |
+----+----------+--------+
|  1 |        1 |    4.5 |
|  5 |        1 |    3.2 |
|  4 |        2 |    3.5 |
|  3 |        2 |    3.7 |
|  6 |        2 |    3.5 |
+----+----------+--------+

https://dev.mysql.com/doc/refman/5.6/ja/limit-optimization.html

0Yu0Yu

エラーメモ

EC2にて

This instance ran out of memory. To free up memory, kill processes by choosing "Tools > Process List" in the menu bar. To migrate this environment to one that has more memory

「ERROR 2006 (HY000) at line ***: MySQL server has gone away」

  • インポートデータサイズのデフォルト値の上限を確認する
    mysql> show variables like 'max_allowed_packet';
  • コマンドから一時的に上限を引き上げる(10MBに設定)
    mysql> set global max_allowed_packet = 1000000;

https://kenzo0107.hatenablog.com/entry/2015/12/17/120010

0Yu0Yu

SHOW TABLEより詳細なテーブル情報を見たい

mysql> SHOW TABLE STATUS;

以下の情報が取得できる。

  • Name:テーブルの名前。
  • Engine:このテーブルのストレージエンジン
  • Version:このテーブルの .frm ファイルのバージョン番号
  • Row_format:行ストレージフォーマット (Fixed、Dynamic、Compressed、Redundant、Compact)。
  • Rows:行数。この値は近似値であり、正確な数を取得するには SELECT COUNT(*) を使用します。
  • INFORMATION_SCHEMA:データベース内のテーブルの場合、Rows値はNULL
  • Avg_row_length:平均行長。
  • Data_length:データファイルの長さ。
  • Max_data_length:データファイルの最大長。これは、このテーブル内に格納できるデータの合計バイト数です (使用されるデータポインタサイズが指定された場合)。
  • Index_length:インデックスファイルの長さ。
  • Data_free:割り当てられているが、使用されていないバイト数。

mysqlshow --status データベース名
でも同じ結果が得られる

https://dev.mysql.com/doc/refman/5.6/ja/show-table-status.html

0Yu0Yu

;の代わりに\Gとすることで、テーブルではなく1つのカラムのデータを一塊として出力できる

$SELECT カラム名1 , [カラム名2 ...] FROM テーブル名 ¥G
0Yu0Yu

pythonでMySQLからcsvファイルを抽出する

cursorについて

MySQLdb(クライアントサイド)の場合はcursor.execute()した時点でクエリ結果は全てロードされている
そのため、fetchoneは一つずつデータを取得するエミュレーションに過ぎない(fetchallで取得した場合とメモリ効率は変わらない)

https://qiita.com/knoguchi/items/3d5631505b3f08fa37cc#結論
http://www.singularpoint.org/blog/sql/select-from-very-huge-table/

0Yu0Yu

fetchallの実装例

# fetchallでデータを取得
rows = cursor.fetchall()

# numには直前のクエリのlimitで取得する行数(n)-1を指定
num = n-1
while num >= 0 :
    for r, last in lastone(rows[num]): # lastoneはループの最後だけ別の処理をする関数
        print(str(r),last)
        csvfile.writelines(str(r)+last)
    csvfile.writelines("\n") # クエリから1列読み込むごとに改行
    num -= 1

出力結果

hogehoge,fugafuga,piyopiyo # rows[0]
hogefuga,fugapiyo,piyohoge # rows[1]
0Yu0Yu

日付からUNIXタイムスタンプに変更する

mysql> SELECT UNIX_TIMESTAMP(time)

UNIXタイムスタンプから日付に変更

mysql> SELECT FROM_UNIXTIME(time)

0Yu0Yu

pythonからSQLをCSVに抽出するあれこれ

PythonでMySQLのデータ操作をする

https://qiita.com/Rino-T/items/6cf515e7e9d2174835fa
https://qiita.com/ta_ta_ta_miya/items/b95c7a2e5e32545c8adc
https://happy-analysis.com/python/python-topic-basic-mysql-derive.html
https://admin-it.xyz/python/python-mysql-access/

pythonでCSVファイルを操作する

https://qiita.com/init/items/0f6b91e89503973826a1 # ヘッダの作成
https://uxmilk.jp/8693
https://note.nkmk.me/python-csv-reader-writer/

CSVに書き出しされるリストの囲い文字を変更するオプション

writer = csv.writer(output_f,
                    delimiter=',',  # 区切り文字はカンマ
                    quotechar='"',  # 囲い文字はダブルクォーテーション
                    quoting=csv.QUOTE_NONNUMERIC)    # 全ての非数値フィールドをクオート

Pythonでダブルクォーテーション囲いのCSVファイルを作成する

0Yu0Yu

DECIMAL型にキャストする

SELECT CAST(数値 AS DECIMAL(全体の桁数, 小数点以下の桁数));

MySQLのCASTでは、FLOATの指定はできません。
そのため、FLOATの代わりにDECIMAL型を用いることで少数でのCASTを実現します。
https://style.potepan.com/articles/19365.html

0Yu0Yu

mysqlでデータを抽出するときに、特定のデータを抽出する

mysql> SELECT * FROM tb WHERE フィールド名 IN("特定の値");

//複数の場合

mysql> SELECT * FROM tb WHERE フィールド名 IN("特定の値","特定の値","特定の値","特定の値");

https://the-zombis.sakura.ne.jp/wp/blog/2012/01/09/post-1163/

0Yu0Yu

キャストで作成したカラム名をSELECTなどで抽出したいときは バックスラッシュ(``)で囲う

0Yu0Yu

比較演算子

内容
フィールド名 = 検索キー(データ) 検索キーと一致する
フィールド名 < 検索キー(データ) 検索キーより小さい
フィールド名 > 検索キー(データ) 検索キーより大きい
フィールド名 >= 検索キー(データ) 検索キー以上
フィールド名 <= 検索キー(データ) 検索キー以下
フィールド名 <> 検索キー(データ) 検索キーと一致しない
http://www.rsch.tuis.ac.jp/~nagai/SYS/SYS22.html
0Yu0Yu
  • テーブルにカラムを追加する
mysql > ALTER TABLE テーブル名  新規カラム名 型情報 オプション;
  • テーブルからカラムを削除する
mysql > ALTER TABLE テーブル名 DROP COLUMN 削除するカラム名;
0Yu0Yu

重複行を弾く

  • GROUP BY句
SELECT カラム名 FROM テーブル名 GROUP BY cカラム名;
  • DISTINCT句
SELECT DISTINCT カラム名 FROM テーブル名;
  • DISTINCTが使えるのは、特定のカラムのユニークな値のみを使うとき
  • これはダメ
SELECT
    DISTINCT `カラム1`,
    DISTINCT `カラム2`
FROM 
     `テーブル名`
  • GROUP BY句の方が処理は高速
  • 上記の2つは暗黙ソートがなされるが、そうではない(レコード数に依存しない)EXISTS句の方が高速

https://qiita.com/Go-Noji/items/5baeb790ade4b57126ff
https://qiita.com/yamadayamada_jp/items/ef7ac4301f9c20491bae