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

データベースにログインする
$ mysql -h host -u user -p menagerie データベース名
Enter password: ********
※menagerieはパスワードではないことに注意。コマンド行で -p オプションのあとにパスワードを入力する場合は、間にスペースを入れずに入力する (たとえば、-p mypassword ではなく、-pmypassword)。

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

テーブルから特定の行だけを取り出す
以下は任意のテーブル(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 |
+--------+-------+---------+------+------------+------------+

基礎知識
カラム名とフィールド名の違い
- カラム名:列名
- フィールド名:項目名
もっというと、
表全体の話はカラム名
表の中のデータの話はフィールド名
と使い分ける。
フィールドは領域、と考えるとわかりやすい。
基本構文

テーブルからカラム一覧を取得したい
mysql> DESCRIBE テーブル名;
or
mysql> SHOW COLUMNS FROM テーブル名;

カラム名の一覧を調べる方法
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 フィールドは、このカラムがインデックス設定されているかどうかを示します。

実行中のクエリの確認
show processlist;

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

エラーメモ
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;

OFFSET句
LIMIT句と組み合わせて使う
LIMITでSELECT文で返す行数を指定し、
OFFSETで先頭の位置を指定する
- 2番目から5番目までの行数を指定する
LIMIT 5 OFFSET 2;
- Webアプリケーションのページング処理も実装できる
- https://qiita.com/egnr-in-6matroom/items/e1beba82d5dc76c85596

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

;
の代わりに\G
とすることで、テーブルではなく1つのカラムのデータを一塊として出力できる
$SELECT カラム名1 , [カラム名2 ...] FROM テーブル名 ¥G

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/

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]

タイムスタンプ型に変換する
mysql> SELECT TIMESTAMP(カラム名);
https://dev.mysql.com/doc/refman/5.6/ja/date-and-time-functions.html#function_timestamp

日付からUNIXタイムスタンプに変更する
mysql> SELECT UNIX_TIMESTAMP(time)
UNIXタイムスタンプから日付に変更
mysql> SELECT FROM_UNIXTIME(time)

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) # 全ての非数値フィールドをクオート

行数を抽出する
mysql> SELECT COUNT(カラム名1), COUNT(カラム名2), COUNT(カラム名3) FROM テーブル名;

INTERSECT句
複数のSELECT結果の重複レコードを取得する

SELECT文で複数テーブルを結合して取得する
mysql> select [カラム名1], [カラム名2] from [テーブル名1],[テーブル名2];
WHERE句
でさらに条件指定(同一カラムの値を比較するなど)
https://rfs.jp/sb/sql/s03/03_2-2.html
https://kowaza.withinit.com/oracle/ora_select_join.html (SQL)

コマンドの実行時間を取得する
mysql -vvv -u root -e "INSERT INTO demo.demo VALUES(1);" | tail -3 | awk -F'(' '{print $2}' | awk -F')' '{print $1}' | awk '{print $1}'

DECIMAL型にキャストする
SELECT CAST(数値 AS DECIMAL(全体の桁数, 小数点以下の桁数));
MySQLのCASTでは、FLOATの指定はできません。
そのため、FLOATの代わりにDECIMAL型を用いることで少数でのCASTを実現します。
https://style.potepan.com/articles/19365.html

CREATE TABLE ... SELECT 構文
mysql> CREATE TABLE new_tbl [AS] SELECT * FROM orig_tbl;

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/

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

比較演算子
式 | 内容 |
---|---|
フィールド名 = 検索キー(データ) | 検索キーと一致する |
フィールド名 < 検索キー(データ) | 検索キーより小さい |
フィールド名 > 検索キー(データ) | 検索キーより大きい |
フィールド名 >= 検索キー(データ) | 検索キー以上 |
フィールド名 <= 検索キー(データ) | 検索キー以下 |
フィールド名 <> 検索キー(データ) | 検索キーと一致しない |
http://www.rsch.tuis.ac.jp/~nagai/SYS/SYS22.html |

- テーブルにカラムを追加する
mysql > ALTER TABLE テーブル名 新規カラム名 型情報 オプション;
- テーブルからカラムを削除する
mysql > ALTER TABLE テーブル名 DROP COLUMN 削除するカラム名;

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