String

Posted by muchag | MySQL | 2015-11-20 (金) 15:10:04

面白い関数もあったよ~♪

【環境】
MySQL:5.5.27, 5.5.38

MySQL:12.5 String Functions
 
文字列処理関数。

REPLACE

REPLACE

書式
  1. REPLACE(str,from_str,to_str)

第1引数:対象文字列
第2引数:検索文字列
第3引数:置換文字列

第1引数の対象文字列には、もちろん直接文字列を指定してもいいんだけど
要はデータを扱いたいので、そこにフィールド名を指定する。
フィールド名の場合は、”” は無し。

  1. UPDATE sample SET name=REPLACE(name, 'Tanaka', 'Yamada');
MySQL | 2015-11-20 (金) 15:10:04 |

CASE

Posted by muchag | MySQL | 2015-11-20 (金) 14:39:18


いわゆる CASE 文。
こんなこともできるなんてね~。

【環境】
MySQL:5.5.27, 5.5.38

MySQL:13.6.5.1 CASE Syntax

書式

THEN の後ろの値が戻ってくる。

  1. CASE case_value
  2.     WHEN when_value THEN statement_list
  3.     [WHEN when_value THEN statement_list] ...
  4.     [ELSE statement_list]
  5. END CASE
  6.  
  7. //
  8. CASE sex
  9.     WHEN 1 THEN '男'
  10.     WHEN 2 THEN '女'
  11.     ELSE 'その他'
  12. END
条件式
  1. CASE
  2.     WHEN search_condition THEN statement_list
  3.     [WHEN search_condition THEN statement_list] ...
  4.     [ELSE statement_list]
  5. END CASE
  6.  
  7. //
  8. CASE
  9.     WHEN sex = 1 THEN '男'
  10.     WHEN sex = 2 THEN '女'
  11.     ELSE 'その他'
  12. END
  13.  
  14. // 不等号はもちろん、IN 句も使える
  15. CASE
  16.     WHEN age IN (13, 14, 15) THEN '中学生'
  17.     WHEN age IN (16, 17, 18) THEN '高校生'
  18.     ELSE 'その他'
  19. END
利用
SELECT

散らばった値を集約して表示できる。

点数に応じて振り分け

80点を超えた人は合格。
60点を超えた人は再テスト。
それ以外の人は不合格。

  1. SELECT
  2.     name, result,
  3.     CASE
  4.         WHEN result > 80 THEN 'Pass'
  5.         WHEN result > 60 THEN 'ReTest'
  6.         ELSE 'Fail'
  7.     END as judgment
  8. FROM test;
集約関数併用
  1. SELECT  dept_nbr,
  2.     COUNT(CASE WHEN sex = 1 THEN 1 ELSE 0 END), // 男の人数
  3.     COUNT(CASE WHEN sex = 2 THEN 1 ELSE 0 END)  // 女の人数
  4. FROM Table_A
  5. GROUP BY dept_nbr;
GROUP BY

散らばった値を集約できる。
ただし、SELECT にも同内容の指定をすること。

豪快に GROUP BY句にも SELECT句の CASE式をコピーしてやるのがポイントです。
単純に「GROUP BY pre_name」と変換前の列を指定すると、
正しい結果が得られませんので注意してください。

ミックのページ:CASE式のススメ

ORDER BY

任意のソート順を設定できる。

CHECK 制約との併用

CASE式は CHECK制約と非常に相性が良いのです。
実際に CASE式を使う局面の半分は CHECK制約の中ではないかと思うほどです。

ミックのページ:CASE式のススメ

と、あるけど、まだ理解できていない。

複数カラムの最大値を返す

ミックのページ:CASE式のススメ 参照。

参考サイト

DBOnline:カラムの値に応じて異なる結果を返す条件式の記述

サンプルコードによるPerl入門:SQLのhaving句はcase式で書くと直感的に記述できる(2011-04-13)

DN-Web64:MySQL : CASE文で複雑な条件を指定
→簡潔で読みやすい。SELECT, GROUP BY, ORDER BY 別にサンプルあり

ミックのページ:CASE式のススメ
→いつもお世話になっております。相変わらずの詳細な解説をありがとうございます。

MySQL | 2015-11-20 (金) 14:39:18 |

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘hoge’ for key ‘PRIMARY’

Posted by muchag | Symfony 1.x | 2015-11-17 (火) 17:52:00

【環境】
Symfony:1.4.13
doctrine:1.2.4
状況

既存データの更新をしようとして起きた。

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry ‘hoge’ for key ‘PRIMARY’

ちょこっといじったら、エラー内容が下記に変わったけど、エラー内容はほぼ同じ?

SQLSTATE[23000]: Integrity constraint violation: 1557 Upholding foreign key constraints for table ‘op_category’, entry ”, key 1 would lead to a duplicate entry
原因

既存データとセーブデータの ID(プライマリーキー)が被ってるよ、という警告のまんま。

経緯

フォームを利用しているものの、Ajax 通信であったため、フォームをそのまま突っ込むのではなく
手動でデータをセットして保存しようとしていた。

Symfony(Doctrine)では、save メソッドで、INSERT と UPDATE を自動判別してくれるとのことで
INSERT のときと、同じデータのセットの仕方にしていたけど
これがいけなかったみたい。

解決

後述の通り、事前にフォームにデフォルト値を設定することで
エラーは消えた。

INSERT と UPDATE を自動判別

フォーム -> 表示(Model 有り) にあるように

  1. $sample = Doctrine::getTable('Sample')->find($request->getParameter('id'));
  2. $this->form = new MySampleForm($sample);

とすることで、フォームのデフォルト値(既存データ)がセットされ
これによって、INSERT と UPDATE を自動判別しているっぽい。

Symfony 1.x | 2015-11-17 (火) 17:52:00 |

SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

Posted by muchag | Symfony 1.x | 2015-11-17 (火) 16:12:02

【環境】
Symfony:1.4.13
doctrine:1.2.4
エラー
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

引数の数が合ってないよっと。

状況1

i18n データを取得しようとして、データ取得 の如く
find メソッドで取得しようとして起きた。

原因

i18n データを取得するのに、親テーブルへアクセスして
Translation テーブルの主キーのデータを渡していた。

  1. $category = Doctrine::getTable('Category')->find(Array($id, $culture));
解決

親テーブルの主キーは ID のみなので、下記のように変更して解決。

  1. $category = Doctrine::getTable('Category')->find($id);
状況2

DQL でサブクエリを利用しようとした。
ただ、メインクエリとサブクエリと
同一のテーブルだった。

  1. $query = Doctrine::getTable('Relation')->createQuery('r')
  2.     ->select('r.hoge_id');
  3.  
  4. $sub_query = $query->createSubquery()
  5.     ->select('sub.hoge_id')
  6.     ->from('Hoge sub')
  7.     ->where('sub.category_id = ?', 123);
  8.    
  9. $query->where("r.hoge_id IN ({$sub_query->getDql()})")
  10.     ->andWhere('r.category_id = ?', 456);
原因

テーブルエイリアスを変えてみたものの
category_id というカラムは同一と見なされ、値は2種類あるので、
数が合ってない、ということみたい。

解決

解決できてないけど、そもそもこの DQL は、本命からずれたお試しだったので
本命の DQL に戻しただけ。

直接の解決策は見つかっていない。

Symfony 1.x | 2015-11-17 (火) 16:12:02 |

Invalid hydration mode specified: ja_JP

Posted by muchag | Symfony 1.x | 2015-11-17 (火) 15:33:17

【環境】
Symfony:1.4.13
doctrine:1.2.4
状況

データ取得 の find メソッドを初めて実装したときに起きた。

Invalid hydration mode specified: ja_JP
原因

複合主キーの検索値を配列ではなく、そのまま引数に入れていたため。

  1. $category = Doctrine::getTable('Category')->find($id, $culture);
解決

配列に書きなおして無事解決。 😯

  1. $category = Doctrine::getTable('Category')->find(Array($id, $culture));
別の問題

この問題は解決したんだけど、別の問題が残っていたのは秘密
下記コードには別の間違いがありました。。。
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

Symfony 1.x | 2015-11-17 (火) 15:33:17 |

フォーマッター(インデントなど)

Posted by muchag | Eclipse | 2015-11-13 (金) 11:55:16

コードのインデントにはタブを利用しないように、という話がある。
でも、コーディング中はタブキーは便利♪
そこで、タブをスペースに変換してくれる Eclipse の機能を利用。

【環境】
Eclipse:4.7
フォーマッター
エクスポート

操作方法は 4.5.1 と変わりなかったけど
初めて JavaScript のフォーマットをいじってみて
困ったのでメモ。

php

php の場合は [フォーマッター] の画面で [エクスポート] できる。

JavaScript

JavaScript の場合は、[編集] の中に入ってから [エクスポート]。

インデント
JavaScript, PHP

従来通り、フォーマッターの中で設定。

HTML, CSS

[Web]-[(当該メニュー)]-[エディター]
[フォーマット]-[スペースを使用したインデント] を選択
インデント・サイズを 2 へ。

行幅
HTML, CSS

[Web]-[(当該メニュー)]-[エディター]
[フォーマット]-[行の幅] を 200 へ。

【環境】
Eclipse:Mars.1 (4.5.1)
  1. [ウィンドウ]-[設定]
  2. [(当該言語)]-[コード・スタイル]-[フォーマッター]
  3. プロファイルを選択
    (独自プロファイルを作りたい場合は、そのまま [編集])
    1. 独自プロファイルを作りたい場合は、[新規]
      1. プロファイル名:任意
      2. 次のプロファイルで設定を初期化:任意
      3. [編集ダイアログをを開く] にチェック(デフォルト)しておけば、そのまま編集画面に入れる
  4. [表示]
  5. インデント
    1. 一般設定
      1. タブ・ポリシー:スペース
      2. インデント・サイズ:4
  6. 中括弧
    1. 中括弧の位置
      1. クラスまたはインターフェースの宣言:次の行
      2. メソッド宣言:次の行
  7. 空白
    1. たくさんありすぎるので、メモれない。プレビューを見ながらどうぞ!
    2. 宣言
    3. 制御ステートメント
    4. 配列
  8. ブランク行
    1. ブランク行
      1. Brefore function / method declarations:1
  9. 制御ステートメント
    1. 一般
      1. 上3つにチェック
    2. ‘if else’
      1. [‘else if’ を1行に保持] にチェック
  10. コメント
    1. 一般設定
      1. [最初の列で行コメントをインデントしない] にチェック
      2. [最初の列で行ブロック・コメントをインデントしない] にチェック
    2. PHPDoc comment settings
      1. [@param タグの後で改行] のチェックを外す
【環境】
Eclipse:4.4
  1. [ウィンドウ]-[設定]
  2. [(当該言語)]-[コード・スタイル]-[フォーマッター]
  3. プロファイルを選択
    (独自プロファイルを作りたい場合は、そのまま [編集])
  4. [編集](Mars(4.5) では [表示])
  5. 独自プロファイルを作りたい場合は、プロファイル名に任意の文字列を入力
  6. [インデント]
    1. タブ・ポリシー:[タブのみ]
    2. ここから先は言語によって仕様が異なるので適宜調整
Eclipse | 2015-11-13 (金) 11:55:16 |

array_reduce

Posted by muchag | PHP | 2015-11-10 (火) 14:00:40

array_reduce は、配列要素を集約して単一の結果を返す関数。
階層構造の再帰処理 で参考にさせていただいたソースに使われていた。

【環境】
php:5.4.7
array_reduce

mixed array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] )

配列 array の各要素に callback 関数を繰り返し適用し、 配列を一つの値に減らします。

php:array_reduce

第1引数:当該配列
第2引数:コールバック関数。無名関数可
第3引数:戻り値の初期値。省略可。省略した場合はデフォルトが null

イメージ

配列について、foreach でグルグル回す代わりに使う。

利用例
  1. // コールバック関数。その1
  2. function sum($carry, $item)
  3. {
  4.     $carry += $item;
  5.     return $carry;
  6. }
  7.  
  8. // コールバック関数。その2
  9. function product($carry, $item)
  10. {
  11.     $carry *= $item;
  12.     return $carry;
  13. }
  14.  
  15. $a = array(1, 2, 3, 4, 5);
  16. $x = array();
  17.  
  18. var_dump(array_reduce($a, "sum")); // int(15)
  19. var_dump(array_reduce($a, "product", 10)); // int(1200), because: 10*1*2*3*4*5
  20. var_dump(array_reduce($x, "sum", "No data to reduce")); // string(17) "No data to reduce"
コールバック関数

関数名そのものを文字列にて渡す。

  1. var_dump(array_reduce($a, "sum"));
無名関数

関数名を指定するのではなく、無名関数にてその場に定義してもOK。

  1. var_dump(array_reduce($a, function sum($carry, $item) {
  2.     $carry *= $item;
  3.     return $carry;
  4.   }
  5. ));
引数

$carry:戻り値。処理の間保持される
$item:配列の各要素。foreach($array as $key => $val) の $val

PHP | 2015-11-10 (火) 14:00:40 |