MySQLのCASE文

使用したことはないけどせっかく覚えたので、一応メモ

SELECT 
    (CASE flag 
    WHEN 1 THEN "フラグ1"
    WHEN 2 THEN "フラグ2"
    ELSE "その他" 
    END) AS flag
FROM users

下記もOK

SELECT 
    (CASE 
    WHEN flag = 1 THEN "フラグ1"
    ELSE "その他" 
    END ) AS flag,
    (CASE 
    WHEN email LIKE '%.jp' THEN "jpn"
    END) AS tlb
FROM users
  • ELSEを記述しない場合はNULLになる

Macのショートカット

主にFinderでの動作
またあれば追加していくかも

ショートカット 動作
探したいファイル名をタイプする そのフォルダ内を検索する
command + Shift + G ファイルのパス表示または移動
command + Shift + C ルートディレクトリへ移動
command + Shift + D デスクトップへ移動
command + Shift + H ホームディレクトリへ移動
command + Shift + U ユーティリティ フォルダへ移動
command + ↑ 一個上の親フォルダを開く
command + ↓ 選択したファイルを開く
command + [ 履歴戻る
command + ] 履歴進む
command + F 検索
command + D 選択したファイルの複製
command + M 最前面のウィンドウを最小化する
command + H 最前面のウィンドウを非表示にする
control + command + スペースバー 文字ビューアの起動

PHPの演算子の優先順位

※過去ブログの転記

 

評価順位 表記 名前 意味
&& 論理積 $a && $b $aと$bがTRUEの時にTRUE
  || 論理和 $a || $b $aまたは$bがTRUEの時にTRUE
  = 代入演算子 $a = $b $aに$bを代入
  and 論理積 $a and $b $aと$bがTRUEの時にTRUE
  xor 排他的論理和 $a xor $b $aか$bどちらかがTRUEの時にTRUE
or 論理和 $a or $b $aまたは$bがTRUEの時にTRUE

ex

//&&,and
$bool = TRUE && FALSE ? 1 : 2;//2
$bool = TRUE and FALSE ? 1 : 2;//TRUE
//||,or
$bool = TRUE || FALSE ? 1 : 2;//1
$bool = TRUE or FALSE ? 1 : 2;//TRUE

and,or=より優先度が低く、$bool = TRUEが実行されるためこのような結果になる

=と同時に使いたい時は条件式を括弧で囲ってあげればOK

$bool = (TRUE and FALSE) ? 1 : 2;//2
$bool = (TRUE or FALSE) ? 1 : 2;//1

xorを初めて知った
どちらか一方がTRUEの場合に時にのみTRUEを返す

$bool = (TRUE xor TRUE) ? 1 : 2;//2
$bool = (TRUE xor FALSE) ? 1 : 2;//1

日毎の登録者数をカウントして歯抜けさせずに日付毎のデータを取得する

※過去ブログの転記

※転記してて思ったが日付の穴埋めくらいアプリケーション側でやれ

 

id create_time
1 2018-09-05 08:00:00
2 2018-09-05 12:35:00
3 2018-08-21 20:10:22
4 2018-09-02 11:10:48
5 2018-09-03 19:13:14

日付毎にユーザーの登録数を取得したい

SELECT 
    COUNT(users.id) AS id, 
    DATE_FORMAT(create_time, "%Y-%m-%d") AS create_time
FROM `users`
GROUP BY DATE_FORMAT(create_time, "%Y-%m-%d") ASC

↓ 結果

user_count create_time
1 2018-08-21
1 2018-09-02
1 2018-09-03
2 2018-09-05

これだとカウント数がない日のデータが取得できない

SELECT
    COALESCE(user_tbl.user_count, 0) AS user_count, /*user_countがNULLの場合は0に変換*/
    date_tbl.`date`
FROM ( 
    SELECT DATE_ADD('2018-08-21', INTERVAL (num.generate_series -1) DAY ) AS `date` /*DATE_ADD()は当日を含めないので-1するか、前月末を基準とする*/
    FROM (
        SELECT 0 AS generate_series
        FROM DUAL 
        WHERE @num := (1 - 1) * 0 
        UNION ALL
        SELECT @num := @num + 1 /*step*/
        FROM `information_schema`.COLUMNS 
        LIMIT 31 /*1ヵ月分を取得するので末日の分だけ日数を取得*/
    ) AS num /*+1していく連番のテーブル*/
) AS date_tbl
LEFT JOIN(
    SELECT COUNT(users.id) AS user_count, DATE_FORMAT(users.create_time, '%Y-%m-%d') AS create_time
    FROM users
    GROUP BY DATE_FORMAT(users.create_time, '%Y-%m-%d') ASC
) AS user_tbl
ON date_tbl.`date` = user_tbl.create_time /*カレンダーの日付と本来のデータの日付をJOIN*/

↓ 結果

user_count create_time
1 2018-08-21
0 2018-08-22
0 2018-08-23
0 2018-08-24
0 2018-08-25
0 2018-08-26
0 2018-08-27
0 2018-08-28
0 2018-08-29
0 2018-08-30
0 2018-08-31
0 2018-09-01
1 2018-09-02
1 2018-09-03
0 2018-09-04
2 2018-09-05
0 2018-09-06

(略)

 

これで歯抜けが埋まる
というか初めて知ったけどdate予約語だと思ってバッククォートで囲ったけど予約語じゃなかった
MySQL :: MySQL 5.6 リファレンスマニュアル :: 9.3 予約語

参考にしたサイト

symfoware.blog.fc2.com

d.hatena.ne.jp

DATE_ADD()で特定の日付のn日後・n日前などの日付を取得する

※過去ブログの転記

 

create_date
2018-09-05
2018-09-05
2018-09-03
2018-09-02
2018-08-21

n日後などの日付を取得する

SELECT
    create_date,
    DATE_ADD(create_date, INTERVAL 10 DAY) AS after_day,/*10日後*/
    DATE_ADD(create_date, INTERVAL -10 DAY) AS before_day,/*10日前*/
    DATE_ADD(create_date, INTERVAL 2 WEEK) AS after_week,/*2週間後*/
    DATE_ADD(create_date, INTERVAL -2 WEEK) AS before_week,/*2週間前*/
    DATE_ADD(create_date, INTERVAL 3 MONTH) AS after_month,/*3ヶ月後*/
    DATE_ADD(create_date, INTERVAL -3 MONTH) AS before_month,/*3ヶ月前*/
    DATE_ADD(create_date, INTERVAL 1 YEAR) AS after_year,/*1年後*/
    DATE_ADD(create_date, INTERVAL -1 YEAR) AS before_year/*1年前*/
FROM users
WHERE 1
ORDER BY create_date DESC

create_date after_day before_day after_week before_week after_month before_month after_year before_year
2018-09-05 2018-09-15 2018-08-26 2018-09-19 2018-08-22 2018-12-05 2018-06-05 2019-09-05 2017-09-05
2018-09-05 2018-09-15 2018-08-26 2018-09-19 2018-08-22 2018-12-05 2018-06-05 2019-09-05 2017-09-05
2018-09-03 2018-09-13 2018-08-24 2018-09-17 2018-08-20 2018-12-03 2018-06-03 2019-09-03 2017-09-03
2018-09-02 2018-09-12 2018-08-23 2018-09-16 2018-08-19 2018-12-02 2018-06-02 2019-09-02 2017-09-02
2018-08-21 2018-08-31 2018-08-11 2018-09-04 2018-08-07 2018-11-21 2018-05-21 2019-08-21 2017-08-21

 

datetime型もOK

create_time
2018-09-05 08:00:00
2018-09-05 12:35:00
2018-08-21 20:10:22
2018-09-02 11:10:48
2018-09-03 19:13:14
SELECT
    create_time,
    DATE_ADD(create_time, INTERVAL 1 HOUR) AS after_hour,/*1時間後*/
    DATE_ADD(create_time, INTERVAL -1 HOUR) AS before_hour,/*1時間前*/
    DATE_ADD(create_time, INTERVAL 30 MINUTE) AS after_minute,/*30分後*/
    DATE_ADD(create_time, INTERVAL -30 MINUTE) AS before_minute,/*30分前*/
    DATE_ADD(create_time, INTERVAL 30 SECOND) AS after_second,/*30秒後*/
    DATE_ADD(create_time, INTERVAL -30 SECOND) AS before_second,/*30秒前*/
    DATE_ADD(create_time, INTERVAL 10 MICROSECOND) AS after_microsecond,/*10マイクロ秒後*/
    DATE_ADD(create_time, INTERVAL -10 MICROSECOND) AS before_microsecond/*10マイクロ秒前*/
FROM users
WHERE 1
ORDER BY create_time DESC

create_time after_hour before_hour after_minute before_minute after_second before_second after_microsecond before_microsecond
2018-09-05 12:35:00 2018-09-05 13:35:00 2018-09-05 11:35:00 2018-09-05 13:05:00 2018-09-05 12:05:00 2018-09-05 12:35:30 2018-09-05 12:34:30 2018-09-05 12:35:00.000010 2018-09-05 12:34:59.999990
2018-09-05 08:00:00 2018-09-05 09:00:00 2018-09-05 07:00:00 2018-09-05 08:30:00 2018-09-05 07:30:00 2018-09-05 08:00:30 2018-09-05 07:59:30 2018-09-05 08:00:00.000010 2018-09-05 07:59:59.999990
2018-09-03 19:13:14 2018-09-03 20:13:14 2018-09-03 18:13:14 2018-09-03 19:43:14 2018-09-03 18:43:14 2018-09-03 19:13:44 2018-09-03 19:12:44 2018-09-03 19:13:14.000010 2018-09-03 19:13:13.999990
2018-09-02 11:10:48 2018-09-02 12:10:48 2018-09-02 10:10:48 2018-09-02 11:40:48 2018-09-02 10:40:48 2018-09-02 11:11:18 2018-09-02 11:10:18 2018-09-02 11:10:48.000010 2018-09-02 11:10:47.999990
2018-08-21 20:10:22 2018-08-21 21:10:22 2018-08-21 19:10:22 2018-08-21 20:40:22 2018-08-21 19:40:22 2018-08-21 20:10:52 2018-08-21 20:09:52 2018-08-21 20:10:22.000010 2018-08-21 20:10:21.999990

フォーマット変えたかったらDATE_FORMAT()してあげれば良い

DATE_FORMAT(DATE_ADD(create_time, INTERVAL 1 HOUR),'%H:%i:%s') AS after_hour,/*1時間後*/

unixtimeのフォーマット変換してDATE_ADD()する

DATE_ADD(FROM_UNIXTIME(create_time,"%Y-%m-%d") , INTERVAL 10 day) AS after_day,/*10日後*/

INTERVALの存在忘れそう

FIND_IN_SET()でカンマ区切りで登録されたカラムの中から特定の値を検索する

※過去ブログの転記

 

---

 

id
3,4,5
2,3
5
1,3,5
4
SELECT *
FROM table
WHERE FIND_IN_SET('5',id)

↓ カンマ区切りで登録された第二引数のカラムの中から第一引数に指定された値を探す

id
3,4,5
5
1,3,5

注意点

  • 文字列の登録など数値以外の登録がある場合は使用しないほうが良い
  • まずないだろうけど1,000みたいな金額を格納するのもやめたほうが良い
  • 設計を見直せ

SELECT文の基本構文と実行順序

※過去ブログの転記

 

構文記述例

SELECT field1, field2
FROM tableA, tableB AS tblB
LEFT JOIN tableC ON tableC.field3 = tblB.field2
WHERE field1 = 1 AND field2 = 2 AND field4 LIKE '%aaa%'
GROUP BY field1, field2 ASC
ORDER BY field1 DESC, field2 
LIMIT 5 OFFSET 10

*1

構文記述順

  1. SELECT
  2. FROM
  3. JOIN
  4. WHERE
  5. GROUP BY
  6. HAVING
  7. ORDER BY
  8. LIMIT
要点
  • GROUP BY / ORDER BY
    • カラム名 並び順 の形式で書く
      ASC → ascending order 1
      DESC → descending order 2
    • 並び順を省略した場合は昇順になる
  • LIMIT
    • LIMIT 取得件数 OFFSET 開始位置
    • LIMIT 開始位置,取得件数の形式でもOK
    • 0から取得する場合はOFFSETは省略可能
  • 共通
    • WHERE句以外は複数指定するときはカンマで繋ぐ
    • テーブル・カラム名MySQL予約語を使用する場合はバッククォートで囲う3

実行順序

  1. FROM
  2. JOIN
  3. WHERE
  4. GROUP BY
  5. HAVING
  6. SELECT
  7. DISTINCT
  8. ORDER BY
  9. LIMIT
要点
  • ORDER BYで集計してからHAVINGで条件指定するよりWHERE句の時点で抽出した方が良い
  • WHEREではSELECTでのエイリアスは使用できないがORDER BYでは使用できる
  • DISTINCTは実行した結果の中から全ての値が一致する重複したレコードを破棄する
  • GROUP BYは実行した結果を指定されたカラムでグループ化する

  1. アスセンディング

  2. ディスセンディング

  3. MySQL :: MySQL 5.6 リファレンスマニュアル :: 9.3 予約語

*1:テーブル構成や結合は適当です...

テーブルの結合について

※過去ブログの転記

 

今まで曖昧にしていた結合についてちゃんとまとめておく

内部結合INNER JOIN / 外部結合LEFT(RIGHT) OUTER JOIN

記述例

SELECT * 
FROM table1 
LEFT JOIN table2 
ON table1.field1 = table2.field2

要点

  • LEFT JOIN,RIGHT JOINLEFT OUTER JOIN,RIGHT OUTER JOINの省略形
  • JOINの条件は複数指定できる
  • 内部結合INNER JOINは結合先のテーブルに指定した条件と一致するレコードがなければ取得しない
  • 外部結合OUTER JOINは一致しないレコードも全て取得する

LEFTとRIGHTの違い

  • LEFTは結合先のテーブルを左に結合する
  • RIGHTは右に結合
FROM table1 LEFT JOIN table2 ON...

table1の左にtable2を外部結合するのでtable1のデータは全て取得する

FROM table1 RIGHT JOIN table2 ON...

table1の右にtable2を外部結合するのでtable2のデータは全て取得する

下記クエリはどちらもtable1の左にtable2を結合する

FROM table1 LEFT JOIN table2 ON...
FROM table2 RIGHT JOIN table1 ON...

補足

SELECT *
FROM table1 
LEFT JOIN table2 
ON table1.field1 = table2.field2

↓ 下と同じだけどJOINした方が処理が速かった

SELECT *
FROM table1,table2
WHERE table1.field1 = table2.field2

 

クロス結合CROSS JOIN

記述例

SELECT * 
FROM table1 
CROSS JOIN table2

要点

  • 2つ以上のテーブルで条件が一致したものを取得する
    (条件を指定した場合はINNER JOINと同じ?)

補足

条件指定なし
SELECT * FROM table1 CROSS JOIN table2

↓ 同じ

SELECT * FROM table1,table2
条件指定あり
SELECT * FROM table1 CROSS JOIN table2 ON table1.field1 = table2.field2

↓ 同じ

SELECT * FROM table1 INNER JOIN table2 ON table1.field1 = table2.field2

 

和結合UNION (DISTINCT) / UNION ALL

記述例

SELECT * FROM table1 
UNION /*UNION ALL*/
SELECT * FROM table2

要点

  • 2つ以上のSELECTの結合
  • デフォルトではUNION DISTINCT が実行される
  • UNIONで結合するテーブルは同じ列数じゃないといけない

CROSS JOINUNIONは正直具体的な恩恵が何かがわからないのであまり深く調べていない...
今まで使ったことがないし使いどころもいまいちわからない

jQueryで入力された値からリアルタイムで消費税込み・抜きの計算をする

瞬時に計算できないアホなので完全に自分用のメモです

¥0 (税込み)
¥0 (税抜き)


一応コード

$(function() {
    var input=$("#input"),tax=1.08,taxIncluded=$("#tax-included"),taxExcluded=$("#tax-excluded");
    input.on("input",function(){
        taxIncluded.text(Math.floor($(this).val() * tax));//税込み・切り捨て
        taxExcluded.text(Math.ceil($(this).val() / tax));//税抜き・切り上げ
    });
}); 

消費税の小数点をどう処理するかが正確に定められていないことを恥ずかしながら初めて知りました

クラス名とか関数で使う表記の言い方

名称 ex
アッパーキャメルケース
パスカルケース
UpperCamelCase
PascalCase
ローワーキャメルケース lowerCamelCase
スネークケース snake_case
チェインケース
ケバブケース
chain-case
kebab-case

特定のカラムから合計を算出して算出した値をWHERE句で抽出したい

※過去ブログの転記

 

MySQLを使って表題の件をやりたかったけど1054 Unknown columnでうまく動かなかったので忘れないようにメモ

ID user_id point
1 1 30
2 1 40
3 1 4
4 1 6
5 2 3
6 2 7

上記のようなテーブルを使用して以下結果のように合計を出してからWHERE句で抽出条件を指定する

user_id total
1 80
2 10
SELECT 
  user_id,
  SUM(point) AS total    
FROM 
  user_points
WHERE 
  total LIKE '%1%'
GROUP BY 
  user_id

↓ エラーが出るので修正

SELECT 
  *
FROM 
  (SELECT 
    user_id,
    SUM(point) AS total
  FROM 
    user_points 
  GROUP BY 
    user_id) AS T1
WHERE 
  total LIKE '%1%'

実行結果

user_id total
2 10

要点

WHEREの中では集計関数(SUM(),AVG() など)やカラムのエイリアスを参照できない


そもそもSELECTの実行順序についても毎度ググってるレベルの曖昧さなので次の記事くらいでちゃんと整理しておきたい

BEMを使用したCSSのclass名の命名規則

※過去ブログの転記

 

CSSでBEMというルールを使用して行う設計方法を初めて知りました。
厳密にはBEMじゃなくてMindBEMding1についてのことをまとめています

MindBEMding

単語 書き方 対象 イメージ
Block block 構成の親となる要素 継承元クラス
Element block__element 子要素 各クラス
Modifier1 block--modifier
block__element--modifier
状態変化を表す メソッド

特徴

  • block と element は__(アンスコx2)で接続
  • block__element__element はNG
  • block もしくは element と modifier は--(ハイフンx2)で接続
  • 単語のつなぎはチェインケース 2
  • modifier の key と value はスネーク(ex. block__element--key_val)
<div class="box">
    <div class="box__ttl">
        <div class="box__ttl--info"></div>
    </div>
</div>
<div class="box-list">
    <div class="box-list__btn">
        <div class="box-list__btn--state_active"></div>
    </div>
</div>

  1. モディファイア

  2. マインドベムディング

  3. ケバブケースとも言うらしい。串刺しになってるように見えるためらしい



 

以上以下とかの範囲がわからない

※過去ブログの転記

 

用語 範囲 不等号 読み方
以上 含む x ≧ 20 大なりイコール 20歳以上 → 20歳~
以下 含む x ≦ 20 小なりイコール 20歳以下 → ~20歳
超え・より大きい 含まない x > 20 大なり 20歳超え → 21歳~
未満・より小さい 含まない x < 20 小なり 20歳未満 → ~19歳

20歳以上30歳以下 = 19歳超え31歳未満 → 20~30歳
20歳超え30歳未満 = 21歳以上29歳以下 → 21~29歳

Markdown記法一覧

※過去ブログの転記

 

 

*1

Markdown記法について忘れやすい表記がいくつかあるのと、知らない表記もいくつかあったのでまとめた。

強調

強調
**強調** or __強調__

斜体字

斜体字
*斜体字* or _斜体字_

取り消し線

取り消し線
~~取り消し線~~

水平ライン


---(ハイフンx3)
or
***(アスタリスクx3)
or
___(アンスコx3)
or
<hr />*2

改行

 

(半角スペース2つ) or <br />

引用

引用テキスト

引用テキスト

>引用テキスト
>>引用テキスト

注釈

注釈元テキスト 1
注釈元テキスト [^注釈id]
[^注釈id]: 注釈先テキスト

リンク

リンクテキスト

[リンクテキスト](https://www.google.com/ "title属性")
or
<https://www.google.com/>*3

定義リンク

定義リンクテキスト

[定義リンクテキスト][id]
[id]: https://www.google.com/ "title属性"

アンカーリンク

アンカーリンク

[アンカーリンク](#アンカーリンク先)

アンカーリンク先

画像

alt属性テキスト

![](https://placehold.jp/20/cacaca/000000/100x50.png?text=image)
![alt属性テキスト](https://placehold.jp/20/cacaca/000000/100x50.png?text=image "title属性")

エスケープ

##エスケープ
\##エスケープ

インラインコード

インラインコード

`バッククォートで囲う`

コードブロック

バッククォートx3で囲う
文頭に半角スペースx4  


チルダx3で囲う

```
バッククォートx3で囲う
```

コードブロック(シンタックスハイライト)

<?php echo $value; ?>
SELECT * FROM table WHERE 1 

*4

<p>テキスト</p>
p {color: #ffffff;}
alert("alert");
```javascript
alert("alert");
```

テーブル

left center right
左寄せ 中央寄せ 右寄せ
|left|center|right|
|:--|:--:|--:|
|左寄せ|中央寄せ|右寄せ|

*5

Tables Generator

リスト

  • list1
  • list2
    • list2-1(半角スペースx2)
    • list2-2
      • list2-2-1(半角スペースx4)
        • list2-2-1-1(半角スペースx6)
    • list2-3
  • list3
- list1
- list2
- list3

or

* list1
* list2
* list3

or

+ list1
+ list2
+ list3

番号付きリスト

  1. list1
  2. list2
    1. list2-1(半角スペースx3)
    2. list2-2
      1. list2-2-1(半角スペースx6)
        1. list2-2-1-1(半角スペースx9)
    3. list2-3
  3. list3
1. list1
1. list2
1. list3

チェックボックス

  • [ ] 未チェック
  • [x] チェック済み
- [ ] 未チェック
- [x] チェック済み

折りたたみ

表示テキスト
長文テキスト長文テキスト長文テキスト長文テキスト長文テキスト

 

<details>
    <summary>表示テキスト</summary>
    <div>
        長文テキスト長文テキスト長文テキスト長文テキスト長文テキスト
    </div>
</details>

初期表示で開いたままにしておきたい場合は<details open>にしておく


  1. 注釈先テキスト

*1:見出しは今更すぎるので省略

*2:Horizontal Ruleの略らしい

*3:メールアドレスの指定も可

*4:MySQL だと色つかなかったから小文字じゃないとダメっぽい?

*5:左右一番端のパイプラインはあってもなくてもOK

.mdファイルをQuick Lookでプレビューしたい

※過去ブログの転記

 

Markdown ファイルを Mac のQuick Lookでプレビューしたかった。

Homebrewのインストール

$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

インストールを確認する

$ brew -v

公式サイト https://brew.sh/index_ja

qlmarkdown のインストール

$ brew cask install qlmarkdown