1対多の関係の属性値について、アプリの検索画面で、andとかorとか括弧とか使った検索をさせる場合にどういうようなテーブル設計にして、どのように検索させれば良いかということについて、とっさに何も思い浮かばなかったので、ちょっと考えてみた。
id1の値が2~10,id2がid1の倍数で最大12まであるゼロ埋め2桁のもの。
検索条件で、+をor,*をand、括弧が使えるもの。
で、id2の検索条件からid1を検索する場合、
条件が"04+06"で、結果が"2,3,4,6",
条件が"04*06"で、検索結果が、"2",
条件が"(06+08)*10"で、結果が、"2",
条件が"06+08*10"で、結果が、"2,3,5,6"
条件が"04*08*12"で、結果が、"2,4"
条件が、12*(05+06+(04*08))で、結果が、"2,3,4,6",
条件が、"05+06*(02+03)"で、id1の検索結果が、"2,3,5"
案1
テーブル構造:tbl(id1,id2)下線は主キー
データ:(2,'02_04_06_08_10_12'),(3,'03_06_09_12'),(4,'04_08_12'),(5,'05_10'),(6,'06_12'),(7,'07'),(8,'08'),(9,'09'),(10,'10')
sql文:
先頭部分は、固定で"select id1 from tbl where "
末尾に動的に追加、
条件が、値の場合、"id2 like '%値%'" を追加し、次の条件を読み取る。
条件が、"+"の場合、" or "を追加し、次の条件を読み取る。
条件が、"*"の場合、" and "を追加し、次の条件を読み取る。
条件が、"-"の場合、次の値まで読んで、id not like '%値%'"を追加し、次の条件を読み取る。
条件が、括弧の場合は、そのまま追加し、次の条件を読み取る。
案2
テーブル構造:tbl(id1,id2) 下線は主キー,インデックスの列の指定順はid2,id1の順
データ:(2,'02'),(2,'04'),(2,'06'),(2,'08'),(2,'10'),(2,'12'),(3,'03'),(3,'06'),(3,'09'),(3,'12'),(4,'04'),(4,'08'),(4,'12'),(5,'05'),(5,'10'),(6,'06'),(6,'12'),(7,'07'),(8,'08'),(9,'09'),(10,'10')
sql文:
固定先頭部分はなしで、
sql文を動的に追加、
条件が、値の場合、"select id1 from tbl where id2='値' "を追加し、次の条件を読み取る。
条件が、"+"の場合、"union "を追加し、次の条件を読み取る。
条件が、"*"の場合、"intersect "を追加し、次の条件を読み取る。
条件が、"-"の場合、"except "を追加し、次の条件を読み取る。
条件が、括弧の場合は、そのまま追加し、次の条件を読み取る。
で、いいのかな?
2012年8月19日日曜日
2009年11月11日水曜日
時刻切り捨ての日付比較のsql文
時刻を無視して、日付だけでシステム日付と比較するSQL
SELECT COL_1,COL_2,...
FROM TABLE_1
WHERE
CONVERT(char, TABLE_1.LastReportDateTime,111) <= CONVERT(char, DATEADD(d, -7, CURRENT_TIMESTAMP), 111)
みたいなものを昔書いた覚えがあるけど、今考えると効率面でよくなかったですね。
問題は2点。TABLE_1の全行に対して、CONVERT関数を呼び出していることと、関数を呼び出した後の比較のため、インデックスが張ってあっても、条件の絞り込みには使えないこと。
以下のように書けば、CONVERT関数を処理するのはCURRENT_TIMESTAMPの1件(SQL処理中はCURRENT_TIMESTAMPは固定値なので)でインデックスが張ってある時に範囲外のものは比較しないで対象外にしてくれそう。
SELECT COL_1,COL_2,...
FROM TABLE_1
WHERE
TABLE_1.LastReportDateTime < CONVERT(char, DATEADD(d, -6, CURRENT_TIMESTAMP), 111)
SELECT COL_1,COL_2,...
FROM TABLE_1
WHERE
CONVERT(char, TABLE_1.LastReportDateTime,111) <= CONVERT(char, DATEADD(d, -7, CURRENT_TIMESTAMP), 111)
みたいなものを昔書いた覚えがあるけど、今考えると効率面でよくなかったですね。
問題は2点。TABLE_1の全行に対して、CONVERT関数を呼び出していることと、関数を呼び出した後の比較のため、インデックスが張ってあっても、条件の絞り込みには使えないこと。
以下のように書けば、CONVERT関数を処理するのはCURRENT_TIMESTAMPの1件(SQL処理中はCURRENT_TIMESTAMPは固定値なので)でインデックスが張ってある時に範囲外のものは比較しないで対象外にしてくれそう。
SELECT COL_1,COL_2,...
FROM TABLE_1
WHERE
TABLE_1.LastReportDateTime < CONVERT(char, DATEADD(d, -6, CURRENT_TIMESTAMP), 111)
登録:
投稿 (Atom)