Drupal で、SQL:Drupal で SQL文を構築した際の細かネタをメモしておく。in構文と、DISTINCT ・・・ 【今日の細ネタ】
やはり様々な理由で、ポテンシャルの高さを実感している。
すばらしい。
しかし、最近はほぼviewsを利用しなくなった。
(ちょっと早すぎ?)
理由は
・明らかに無駄なSQL文で動いていることが
多く見受けられること
・(ほんの少しだけどやはり?)重さを感じること
・データベースに踏み込んで、Drupalのテーブル構造を
肌で感じたいこと
・・・様々だけれど。
主に、
・(不明な場合は)viewsを作業用に作成し、
そこで生成され表示されるSQL文と、
・phpMyAdmin利用したテーブル構造の再確認
で、自力でSQL文を使うことが多い。
今日も2つほど、「覚えておこ」という
細ネタがあったので記録しておく。
【2010年05月04日 のコマネタ】
□Drupalにおいて、pager_query使うときに注意
その1:like '%strtext%' ではなく、in構文が確実(?)
その2:集計関数を使う際の DISTINCT 再理解
□jQueryって、簡易デバッグにも便利
追記に ▼
************************************************
◎ Drupal で SQL文を構築した際の細かネタ の巻
:今日の細ネタ
************************************************
■Drupalにおいて、pager_query使うとき。
・pager_quer 自体は素晴らしくて多用している。
(参照)Drupal pager_query:Pager続き。今度は、Drupalサイト。当然モジュールかAPIであるんだろうな ・・・ 【今日のDrupal】
□症状
・これを利用するには、
function pager_query(
$query,
$limit = 10,
$element = 0,
$count_query = NULL)
で、4つの引数
・検索本SQL
・頁の表示点数
・複数利用できるelement値
・カウント用のSQL
を与えるわけだが・・・
どうもおかしい。
時折、クエリがうまくできなくて
0 が返ってくるのだ。
・false ではない
・当該SQLを直接データベースに投げると
きちんと答えを返してくる。
・この関数内を少し覗いてみる。
□$args = func_get_args();
※関数の引数リストを配列として返す
その後
□$args = array_slice($args, 4);
※配列の一部を展開
これはつまり、予定されてる4つ以降の引数を
取得把握しようとしている?
□
// Alternative syntax for '...'
if (isset($args[0]) && is_array($args[0])) {
$args = $args[0];
}
※取得できそれが配列であれば、それ自体を
引数扱いとする・・・と。
□$count_query = NULL
カウント用のSQLがなければ、
// Construct a count query if none was given.
if (!isset($count_query)) {
$count_query = preg_replace(array('/SELECT.*?FROM /As', '/ORDER BY .*/'), array('SELECT COUNT(*) FROM ', ''), $query);
}
□そして最終的に
$pager_total_items[$element] = db_result(db_query($count_query, $args));
取得件数をまず得るのだが、
ここで、返りが0 になってしまうケースがある。
※投げている、$count_query を直接データベースに
あてると、正常に返ってくるのに・・・
□どうも、この先、Drupal で
・includes/database.mysql.inc において、
function db_result($result) {
if ($result && mysql_num_rows($result) > 0) {
// The mysql_fetch_row function has an optional second parameter $row
// but that can't be used for compatibility with Oracle, DB2, etc.
$array = mysql_fetch_row($result);
return $array[0];
}
return FALSE;
}
値を返してくれていないようなのだ。
いろいろ探ったけどわからなかった。
□回避
検索を行う場合、 targetitem like = '%targetstr%' ではなくて
> targetitem in ('targetstr') を利用することで
正常に値を得ることができるようになった。
※一応正常に動いているようなので回避。
しかし、知識疑問としての課題 残り。
------------------------------------------------
■SQL構文はそれ自体、奥深くて面白いのだが
普段利用するときは基本的な構文のみで事足りる。
しかし、知識は不安定であること、今日思い知った。
□例
・ある 商品テーブルがあり、
・そこには、2レベルのカテゴリマスタの
・子カテゴリへのリンクが複数登録されているとする。
・つまり、商品Aが、
カテゴリ(あ)> 子カテゴリ(イ) と
カテゴリ(え)> 子カテゴリ(ハ) に
属している・・・という場合
・リレーションは別のリレーショナルテーブル
(子カテゴリリレーショナルテーブル)で
保存されている
商品Aid | 子カテゴリ(イ)id
商品Aid | 子カテゴリ(ハ)id
・・・・・
・子カテゴリテーブルには
(親)カテゴリへのリレーションが設定されている
子カテゴリ(イ) | カテゴリ(あ)id
子カテゴリ(ハ) | カテゴリ(え)id
・・・・・
・検索SQLで、親カテゴリ(あ)のカテゴリ名前で
商品を全検索したい場合
SELECT *
FROM 商品テーブル
LEFT JOIN 子カテゴリリレーショナルテーブル
ON 子カテゴリリレーショナルテーブル.商品id =商品テーブル.商品id
LEFT JOIN 子カテゴリテーブル
ON 子カテゴリテーブル.子カテゴリid = 子カテゴリリレーショナルテーブル.子カテゴリid
LEFT JOIN カテゴリテーブル
ON カテゴリテーブル.カテゴリid = 子カテゴリテーブル.カテゴリid
WHERE (カテゴリテーブル.カテゴリ名前 in ('検索する文字列'))
ORDER BY カテゴリテーブル.カテゴリ名前 ASC
このときに、重複を回避するために、distinct を利用し、
SELECT distinct
・・・・・
さらに集計関数を利用した場合、
SELECT COUNT(DISTINCT id) AS row_count
・・・・・
※ DISTINCT * ではエラーになる。
このあたり、色々試してやっと理解できた。恥ずかし。
------------------------------------------------
■jQuery ってほんとに便利だなぁ。
もっとよく知ることにより、開発ももっと
確実性も効率も向上するんだろうなぁ・・・
□ケース
先の投稿で、(いまさらながら)jQuery.dump.js という
プラグインを知り、
・jQuery.dump.js:知、知らなかった。こんな便利なjQueryプラグインがあったのか。もっとい早く知っていれば。DOMの情報をdump出力してくれる ・・・ 【jQueryプラグイン】
それはそれで喜んだのだけど。
そのとき、ある<span> 要素のcalss名をとろうとしたのだけで
うまくとれなかった。
こんなときも、jQuery 利用すれば、
・確実に
・きれいに取得してくれる。
var $target = $(this);
var classname = $target.attr('class');
※DOMはほんとに奥深く、対象がテキスト文字列であっても
それを どうハンドリングするかによって
取れたり取れなかったりする。
それが、jQueryの簡単な構文で楽に取得できるのは有難い。
これをうまく利用した、簡単なデバッグ用関数を作り、
デバッグ時に利用しよう。
※取りとめもないメモ。乱文ご容赦。