お試しでやってみる?
水曜日, 3月 12, 2008
水曜日, 12月 26, 2007
表の統計データを変更する
Ask Tom "SQL Tuning"
表の統計データを変更することで、大量データを作成せず、実行計画に影響を与えることができる。
通常の統計データの取得は
表の統計データを変更することで、大量データを作成せず、実行計画に影響を与えることができる。
通常の統計データの取得は
exec dbms_stats.gather_table_stats (user,'t');
統計データ変更方法は
exec dbms_stats.set_table_stats( user, 'PERSON', numrows=>1000000, numblks=>100000 );
プロシージャ:set_table_statsの詳細は
http://otndnld.oracle.co.jp/document/products/oracle10g/102/doc_cd/appdev.102/B19245-01/d_stats.htm#sthref8385
金曜日, 12月 21, 2007
PL/SQLで検索結果リストをIN句に利用する
Ask Tom "varying elements in IN list"
なぜか、パッケージの中にTYPE宣言をすると、エラーになってしまうので、
仕方なく、
CREATE OR REPLACE TYPE XXXTYPE AS TABLE OF NUMBER;
で作成して、
PL/SQLでは
AND XXX_ID IN (SELECT * FROM TABLE( CAST (memberIdList AS memberIdTab)))
のようにすることで、なんとなく解決。
ちなみに、ファンクションでCURSORを返すのは、
OPEN cur1 FOR
SELECT ....
;
RETURN cur1;
ではうまくいくが、
SQLを事前に宣言してから、OPENだけで、次にRETURNしようとするとエラーになってしまう。
なぜだ。。。
なぜか、パッケージの中にTYPE宣言をすると、エラーになってしまうので、
仕方なく、
CREATE OR REPLACE TYPE XXXTYPE AS TABLE OF NUMBER;
で作成して、
PL/SQLでは
AND XXX_ID IN (SELECT * FROM TABLE( CAST (memberIdList AS memberIdTab)))
のようにすることで、なんとなく解決。
ちなみに、ファンクションでCURSORを返すのは、
OPEN cur1 FOR
SELECT ....
;
RETURN cur1;
ではうまくいくが、
SQLを事前に宣言してから、OPENだけで、次にRETURNしようとするとエラーになってしまう。
なぜだ。。。
木曜日, 12月 13, 2007
Tomcat 6で実現! Ajaxを超える通信技術Comet (1/3) - @IT
Tomcat 6で実現! Ajaxを超える通信技術Comet (1/3) - @IT
なかなか面白い、
通常のWEBアプリケーションでサーバー側のデータ変更をリアルタイムで更新するためには
AJAXなどを利用して、定期的にサーバーにリクエストを送るしかいないが、
Cometを利用すると、HTTPコネクションを開きぱなしにして、
サーバー側から更新データを随時送る仕組み
WEBでチャットのようなリアルタイム更新アプリケーションの実装ができるって!
1Request:1Reponseを「プル型の通信」と言うと
こちらは疑似的な「プッシュ型の通信」になる。
TomcatではComet実行コネクタとして、
NIO(New I/O)とAPR(Apache Portable Runtime)がある。
Tomcatのserver.xmlを修正してNIOを利用する例:
protocol="org.apache.coyote.http11.Http11NioProtocol"
リバースAjax機能はAjax+Javaをもっとやさしくする?
なかなか面白い、
通常のWEBアプリケーションでサーバー側のデータ変更をリアルタイムで更新するためには
AJAXなどを利用して、定期的にサーバーにリクエストを送るしかいないが、
Cometを利用すると、HTTPコネクションを開きぱなしにして、
サーバー側から更新データを随時送る仕組み
WEBでチャットのようなリアルタイム更新アプリケーションの実装ができるって!
1Request:1Reponseを「プル型の通信」と言うと
こちらは疑似的な「プッシュ型の通信」になる。
TomcatではComet実行コネクタとして、
NIO(New I/O)とAPR(Apache Portable Runtime)がある。
Tomcatのserver.xmlを修正してNIOを利用する例:
protocol="org.apache.coyote.http11.Http11NioProtocol"
リバースAjax機能はAjax+Javaをもっとやさしくする?
木曜日, 11月 29, 2007
Geekなぺーじ : 10のUNIX小技
Geekなぺーじ : 10のUNIX小技
①:複数階層のフォルダを一回で作成する。
[root@localhost ~]# mkdir -p a/b/c
[root@localhost ~]# mkdir -p a/{lib,src/doc/{html,pdf,txt}}
mkdirに-pオプションがない場合、mkdirhierを使うことが出来るらしい。
と書いてあったけど、RadhatAS4ではだめだった。
[root@localhost ~]# mkdirhier -p a/{lib,src/doc/{html,pdf,txt}} -- NG
②:tarの解凍先を指定する。
[root@localhost ~]# tar xfv a.tar -C /tmp/a/b
③:コマンドを演算子で繋げる
一つ目のコマンドが成功した(return 0)場合にだけ実行
[root@localhost ~]# cd tmp/a/b/c && tar xvf ~/archive.tar
一つ目のコマンドが失敗した(return 0以外)場合にだけ実行
[root@localhost ~]# cd tmp/a/b/c || mkdir -p tmp/a/b/c
[root@localhost ~]# cd tmp/a/b || mkdir -p tmp/a/b && tar xvf -C tmp/a/b ~/a.tar
④:変数と「"」の組み合わせは慎重に
[root@localhost ~]#
[root@localhost ~]# ls tmp/
a b
[root@localhost ~]# VAR="tmp/*"
[root@localhost ~]# echo $VAR
tmp/a tmp/b
[root@localhost ~]# echo "$VAR"
tmp/*
[root@localhost ~]# echo $VARa
[root@localhost ~]# echo "$VARa"
[root@localhost ~]# echo "${VAR}a"
tmp/*a
[root@localhost ~]# echo ${VAR}a
tmp/a
[root@localhost ~]#
⑤:長い入力にはエスケープシーケンスを利用
[root@localhost ~]# cd tmp/a/b/c || \
> mkdir -p tmp/a/b/c && \
> tar xvf -C tmp/a/b/c ~/archive.tar
でも
[root@localhost ~]# cd tmp/a/b/c \
はNGだった。
⑥:コマンドをグループ分けする
[root@localhost ~]# ( cd tmp/a/b/c/ || mkdir -p tmp/a/b/c && \
> VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar ) \
> | mailx admin -S "Archive contents"
<>
[root@localhost ~]# { cp ${VAR}a . && chown -R guest.guest a && \
> tar cvf newarchive.tar a; } | mailx admin -S "New archive"
「{}」の前後にスペースが入るように注意しましょう。
スペースを入れないと正しく動作しないかも知れません。
また、「}」の前に来る最後のコマンドの後に「;」を入れる。
⑦:xargsをfind以外と組み合わせる
[root@localhost ~]# find 何か どこかへのパス | \
> xargs ファイル名を使う何らかのコマンド
$ xargs
a
b
c
コントロールキー+p
a b c
ファイル名を出力する他のコマンドと組み合わせる事も可能です。
$ ls | xargs
December_Report.pdf README a archive.tar mkdirhier.sh
$ ls | xargs file
December_Report.pdf: PDF document, version 1.3
README: ASCII text
a: directory
archive.tar: POSIX tar archive
mkdirhier.sh: Bourne shell script text executable
複数行を一行にまとめる事も出来ます。
$ ls -l | xargs
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 \
root root 238 Dec 03 08:19 README drwxr-xr-x 38 joe joe 354082 Nov 02 \
16:07 a -rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar -rwxr-xr-x 1 \
joe joe 3239 Sep 30 12:40 mkdirhier.sh
xargs利用上の注意
「_(アンダースコア、下棒)」はEOFとして扱われます。
そのため、その文字がxargsに渡されると、
それ以降の項目は無視されてしまいます。
この問題を回避するには-eオプションを利用してください。
⑧:grepに行数をカウントさせる
wc -l と組み合わせるのではなく、grep の-cオプションを使った方が行数の計算は速いです。
$ time grep PATTERN longfile.txt | wc -l
2811
real 0m0.097s
user 0m0.006s
sys 0m0.032s
$ time grep -c PATTERN longfile.txt
2811
real 0m0.013s
user 0m0.006s
sys 0m0.005s
grepがカウントすべきではないとき
-cオプションは、マッチした行数のみをカウントします。
-oオプションは、マッチしたパターン自体を出力します。
単一行にマッチするパターンが複数回登場する時などには、
-oオプションにより標準出力に出される行数と、
-c が行った結果のカウント数が異なってしまいます。
そのような場合には、wc -l を使いましょう。
grep -o PATTERN longfile.txt | wc -l
⑨:パターンマッチは行全体ではなくフィールドで
grepなどで行全体をマッチするのではなく、
awkで特定のフィールドを指定してパターンマッチをすべきです。
grepで行全体をマッチさせてしまうと、意図しないものも結果に入ってしまうことがあります。
例えば、ファイル更新日が12月のものを探している時に、
1月に更新したDecemberReport.pdfが結果に入ってしまう場合があります。
悪い例
ls -l | grep Dec
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf
-rw-r--r-- 1 root root 238 Dec 03 08:19 README
-rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar
良い例
ls -l | awk '$6 == "Dec"'
-rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar
-rw-r--r-- 1 root root 238 Dec 03 08:19 README
⑩:無駄なcatとパイプは行わない
grepなどのコマンドを使う時に、catをパイプで繋げてgrepの標準入力に流し込むのは無駄です。
grepなどの大抵のコマンドには、ファイル名をオプションとして渡せる機能があります。
以下に速度の比較を示します。
$ time cat longfile.txt | grep PATTERN
2811
real 0m0.015s
user 0m0.003s
sys 0m0.013s
$ time grep PATTERN longfile.txt
2811
real 0m0.010s
user 0m0.006s
sys 0m0.004s
---------------------------
いろいろ出来ますね。勉強になりました。
①:複数階層のフォルダを一回で作成する。
[root@localhost ~]# mkdir -p a/b/c
[root@localhost ~]# mkdir -p a/{lib,src/doc/{html,pdf,txt}}
mkdirに-pオプションがない場合、mkdirhierを使うことが出来るらしい。
と書いてあったけど、RadhatAS4ではだめだった。
[root@localhost ~]# mkdirhier -p a/{lib,src/doc/{html,pdf,txt}} -- NG
②:tarの解凍先を指定する。
[root@localhost ~]# tar xfv a.tar -C /tmp/a/b
③:コマンドを演算子で繋げる
一つ目のコマンドが成功した(return 0)場合にだけ実行
[root@localhost ~]# cd tmp/a/b/c && tar xvf ~/archive.tar
一つ目のコマンドが失敗した(return 0以外)場合にだけ実行
[root@localhost ~]# cd tmp/a/b/c || mkdir -p tmp/a/b/c
[root@localhost ~]# cd tmp/a/b || mkdir -p tmp/a/b && tar xvf -C tmp/a/b ~/a.tar
④:変数と「"」の組み合わせは慎重に
[root@localhost ~]#
[root@localhost ~]# ls tmp/
a b
[root@localhost ~]# VAR="tmp/*"
[root@localhost ~]# echo $VAR
tmp/a tmp/b
[root@localhost ~]# echo "$VAR"
tmp/*
[root@localhost ~]# echo $VARa
[root@localhost ~]# echo "$VARa"
[root@localhost ~]# echo "${VAR}a"
tmp/*a
[root@localhost ~]# echo ${VAR}a
tmp/a
[root@localhost ~]#
⑤:長い入力にはエスケープシーケンスを利用
[root@localhost ~]# cd tmp/a/b/c || \
> mkdir -p tmp/a/b/c && \
> tar xvf -C tmp/a/b/c ~/archive.tar
でも
[root@localhost ~]# cd tmp/a/b/c \
はNGだった。
⑥:コマンドをグループ分けする
> VAR=$PWD; cd ~; tar xvf -C $VAR archive.tar ) \
> | mailx admin -S "Archive contents"
<
[root@localhost ~]# { cp ${VAR}a . && chown -R guest.guest a && \
> tar cvf newarchive.tar a; } | mailx admin -S "New archive"
「{}」の前後にスペースが入るように注意しましょう。
スペースを入れないと正しく動作しないかも知れません。
また、「}」の前に来る最後のコマンドの後に「;」を入れる。
⑦:xargsをfind以外と組み合わせる
[root@localhost ~]# find 何か どこかへのパス | \
> xargs ファイル名を使う何らかのコマンド
$ xargs
a
b
c
コントロールキー+p
a b c
ファイル名を出力する他のコマンドと組み合わせる事も可能です。
$ ls | xargs
December_Report.pdf README a archive.tar mkdirhier.sh
$ ls | xargs file
December_Report.pdf: PDF document, version 1.3
README: ASCII text
a: directory
archive.tar: POSIX tar archive
mkdirhier.sh: Bourne shell script text executable
複数行を一行にまとめる事も出来ます。
$ ls -l | xargs
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf -rw-r--r-- 1 \
root root 238 Dec 03 08:19 README drwxr-xr-x 38 joe joe 354082 Nov 02 \
16:07 a -rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar -rwxr-xr-x 1 \
joe joe 3239 Sep 30 12:40 mkdirhier.sh
xargs利用上の注意
「_(アンダースコア、下棒)」はEOFとして扱われます。
そのため、その文字がxargsに渡されると、
それ以降の項目は無視されてしまいます。
この問題を回避するには-eオプションを利用してください。
⑧:grepに行数をカウントさせる
wc -l と組み合わせるのではなく、grep の-cオプションを使った方が行数の計算は速いです。
$ time grep PATTERN longfile.txt | wc -l
2811
real 0m0.097s
user 0m0.006s
sys 0m0.032s
$ time grep -c PATTERN longfile.txt
2811
real 0m0.013s
user 0m0.006s
sys 0m0.005s
grepがカウントすべきではないとき
-cオプションは、マッチした行数のみをカウントします。
-oオプションは、マッチしたパターン自体を出力します。
単一行にマッチするパターンが複数回登場する時などには、
-oオプションにより標準出力に出される行数と、
-c が行った結果のカウント数が異なってしまいます。
そのような場合には、wc -l を使いましょう。
grep -o PATTERN longfile.txt | wc -l
⑨:パターンマッチは行全体ではなくフィールドで
grepなどで行全体をマッチするのではなく、
awkで特定のフィールドを指定してパターンマッチをすべきです。
grepで行全体をマッチさせてしまうと、意図しないものも結果に入ってしまうことがあります。
例えば、ファイル更新日が12月のものを探している時に、
1月に更新したDecemberReport.pdfが結果に入ってしまう場合があります。
悪い例
ls -l | grep Dec
-rw-r--r-- 7 joe joe 12043 Jan 27 20:36 December_Report.pdf
-rw-r--r-- 1 root root 238 Dec 03 08:19 README
-rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar
良い例
ls -l | awk '$6 == "Dec"'
-rw-r--r-- 3 joe joe 5096 Dec 14 14:26 archive.tar
-rw-r--r-- 1 root root 238 Dec 03 08:19 README
⑩:無駄なcatとパイプは行わない
grepなどのコマンドを使う時に、catをパイプで繋げてgrepの標準入力に流し込むのは無駄です。
grepなどの大抵のコマンドには、ファイル名をオプションとして渡せる機能があります。
以下に速度の比較を示します。
$ time cat longfile.txt | grep PATTERN
2811
real 0m0.015s
user 0m0.003s
sys 0m0.013s
$ time grep PATTERN longfile.txt
2811
real 0m0.010s
user 0m0.006s
sys 0m0.004s
---------------------------
いろいろ出来ますね。勉強になりました。
木曜日, 11月 08, 2007
Ask Tom "SQL Query to find gaps in date ranges"
Ask Tom "SQL Query to find gaps in date ranges"
with data as (select max(c-b) c_b from t), r as (select level-1 l from data connect by level <= c_b) select .....
if you do the "data" one, you do not need the case statement as protection...
ops$tkyte%ORA10GR2> variable x number
ops$tkyte%ORA10GR2> exec :x := 50
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> with
2 r as
3 (select level-1 l
4 from dual
5 connect by level <= :x
6 )
7 select last_dt+1, dt-1
8 from (
9 select dt, lag(dt) over (order by dt) last_dt
10 from (
11 select distinct t.b+r.l dt
12 from t, r
13 where r.l <= t.c-t.b and case when t.c-t.b > :x then 1/0 end is null
14 )
15 )
16 where last_dt <> dt-1
17 /
LAST_DT+1 DT-1
--------- ---------
02-FEB-07 04-FEB-07
writing is gleaned through experience, time, effort and mentoring. Anyone can do it.
create table t ( a int, b date, c date );
insert into t values(1, to_date( '01-jan-2007'), to_date( '15-jan-2007'));
insert into t values(2, to_date( '03-jan-2007'), to_date( '10-jan-2007'));
insert into t values(3, to_date( '12-jan-2007'), to_date( '25-jan-2007'));
insert into t values(4, to_date( '20-jan-2007'), to_date( '01-feb-2007'));
insert into t values(5, to_date( '05-feb-2007'), to_date( '10-feb-2007'));
insert into t values(6, to_date( '05-feb-2007'), to_date( '28-feb-2007'));
insert into t values(7, to_date( '10-feb-2007'), to_date( '15-feb-2007'));
insert into t values(8, to_date( '18-feb-2007'), to_date( '23-feb-2007'));
insert into t values(9, to_date( '22-feb-2007'), to_date( '16-mar-2007'));
From the above example, the gap that exists is:
02-feb-2007 --> 04-feb-2007
and we said...
Here is one approach. I used "50" - you can replace 50 with a 'better' value, or you could usewith data as (select max(c-b) c_b from t), r as (select level-1 l from data connect by level <= c_b) select .....
if you do the "data" one, you do not need the case statement as protection...
ops$tkyte%ORA10GR2> variable x number
ops$tkyte%ORA10GR2> exec :x := 50
PL/SQL procedure successfully completed.
ops$tkyte%ORA10GR2> with
2 r as
3 (select level-1 l
4 from dual
5 connect by level <= :x
6 )
7 select last_dt+1, dt-1
8 from (
9 select dt, lag(dt) over (order by dt) last_dt
10 from (
11 select distinct t.b+r.l dt
12 from t, r
13 where r.l <= t.c-t.b and case when t.c-t.b > :x then 1/0 end is null
14 )
15 )
16 where last_dt <> dt-1
17 /
LAST_DT+1 DT-1
--------- ---------
02-FEB-07 04-FEB-07
writing is gleaned through experience, time, effort and mentoring. Anyone can do it.
木曜日, 3月 01, 2007
木曜日, 11月 30, 2006
水曜日, 11月 29, 2006
AskTom "Update statement tuning"
AskTom "Update statement tuning"
and multi_block_read are always physical I/O?
NO!
say your multi-block read count is set reasonable (1000 isn't even borderline
reasonable), say at 64.
[quote]
but block 15, 30, and 45 are in the cache.
we'll multiblock physical IO 1..14
single block logical IO 15
multiblock physical IO 16..29
and so on.
[/quote]
and multi_block_read are always physical I/O?
NO!
say your multi-block read count is set reasonable (1000 isn't even borderline
reasonable), say at 64.
[quote]
but block 15, 30, and 45 are in the cache.
we'll multiblock physical IO 1..14
single block logical IO 15
multiblock physical IO 16..29
and so on.
[/quote]
木曜日, 9月 28, 2006
土曜日, 9月 09, 2006
SQLTIP--PASCAL△
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
...
++++++++++++++++++++++++++++++++++++++++++++
SELECT EXP (SUM (LN (GREATEST (LEVEL - 1, 1))) OVER ())
/ EXP (SUM (LN (GREATEST (LEVEL - 1, 1))) OVER (ORDER BY LEVEL))
/ EXP (SUM (LN (GREATEST (&n - LEVEL, 1))) OVER (ORDER BY LEVEL DESC)) pascal
FROM DUAL
CONNECT BY LEVEL <= &n
/
1 1
1 2 1
1 3 3 1
1 4 6 4 1
...
...
++++++++++++++++++++++++++++++++++++++++++++
SELECT EXP (SUM (LN (GREATEST (LEVEL - 1, 1))) OVER ())
/ EXP (SUM (LN (GREATEST (LEVEL - 1, 1))) OVER (ORDER BY LEVEL))
/ EXP (SUM (LN (GREATEST (&n - LEVEL, 1))) OVER (ORDER BY LEVEL DESC)) pascal
FROM DUAL
CONNECT BY LEVEL <= &n
/
SQLTIP--Fibonacci
SELECT ( POWER ((1 + SQRT (5)) / 2, LEVEL)
- POWER ((1 - SQRT (5)) / 2, LEVEL)
)
/ SQRT (5) fibonacci
FROM DUAL
CONNECT BY LEVEL <= 20
/
SELECT ( POWER ((1 + SQRT (5)) / 2, LEVEL)
- POWER ((1 - SQRT (5)) / 2, LEVEL)
)
/ SQRT (5) fibonacci,
(5 + 3 * SQRT (5)) * POWER ((1 + SQRT (5)) / 2, LEVEL)
/ 10
+ (5 - 3 * SQRT (5)) * POWER ((1 - SQRT (5)) / 2, LEVEL) / 10
- 1 sum_n
FROM DUAL
CONNECT BY LEVEL <= 20
/
- POWER ((1 - SQRT (5)) / 2, LEVEL)
)
/ SQRT (5) fibonacci
FROM DUAL
CONNECT BY LEVEL <= 20
/
SELECT ( POWER ((1 + SQRT (5)) / 2, LEVEL)
- POWER ((1 - SQRT (5)) / 2, LEVEL)
)
/ SQRT (5) fibonacci,
(5 + 3 * SQRT (5)) * POWER ((1 + SQRT (5)) / 2, LEVEL)
/ 10
+ (5 - 3 * SQRT (5)) * POWER ((1 - SQRT (5)) / 2, LEVEL) / 10
- 1 sum_n
FROM DUAL
CONNECT BY LEVEL <= 20
/
SQLTIP--文字列を特定数の単語単位で改行する。
str
--------------------------------
This is not a verry long test string
Happy new year !
id string
----------------------
1 This is not a
1 verry long test
1 string
2 Happy new year
2 !
SELECT ID, STRING
FROM (SELECT level#, rnum ID,
SUBSTR (str, INSTR (str, base, 1, level#) + len,
INSTR (SUBSTR (str, INSTR (str, base, 1, level#) + len,
limit# + 1), base, -1) - 1) STRING,
INSTR (str, base, 1, level#) + len - 1 start#,
INSTR (SUBSTR (str, INSTR (str, base, 1, level#) + len,
limit# + 1), base, -1) +
INSTR (str, base, 1, level#) + len - 1 end#
FROM (SELECT LEVEL level#, limit#, base, len
FROM (SELECT MAX ( LENGTH (str)
- LENGTH (REPLACE (str, ' ')) + 1) max_part,
15 limit#, ' ' base, LENGTH (' ') len
FROM TEST)
CONNECT BY LEVEL <= max_part),
(SELECT ROWNUM rnum, ' ' || str || ' ' str,
LENGTH (str) - LENGTH (REPLACE (str, ' ')) + 1 part
FROM TEST)
WHERE level# <= part)
START WITH start# = 1
CONNECT BY PRIOR end# = start# AND PRIOR ID = ID
GROUP BY ID, level#, STRING
/
--------------------------------
This is not a verry long test string
Happy new year !
id string
----------------------
1 This is not a
1 verry long test
1 string
2 Happy new year
2 !
SELECT ID, STRING
FROM (SELECT level#, rnum ID,
SUBSTR (str, INSTR (str, base, 1, level#) + len,
INSTR (SUBSTR (str, INSTR (str, base, 1, level#) + len,
limit# + 1), base, -1) - 1) STRING,
INSTR (str, base, 1, level#) + len - 1 start#,
INSTR (SUBSTR (str, INSTR (str, base, 1, level#) + len,
limit# + 1), base, -1) +
INSTR (str, base, 1, level#) + len - 1 end#
FROM (SELECT LEVEL level#, limit#, base, len
FROM (SELECT MAX ( LENGTH (str)
- LENGTH (REPLACE (str, ' ')) + 1) max_part,
15 limit#, ' ' base, LENGTH (' ') len
FROM TEST)
CONNECT BY LEVEL <= max_part),
(SELECT ROWNUM rnum, ' ' || str || ' ' str,
LENGTH (str) - LENGTH (REPLACE (str, ' ')) + 1 part
FROM TEST)
WHERE level# <= part)
START WITH start# = 1
CONNECT BY PRIOR end# = start# AND PRIOR ID = ID
GROUP BY ID, level#, STRING
/
SQLTIP--任意の範囲の数値、日付を出力する。
1から100まで出力
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 100
/
20060730から20060830まで出力
SELECT (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) day#
FROM DUAL
CONNECT BY (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) <=
TO_DATE ('20060830', 'YYYYMMDD')
/
或は
SELECT *
FROM (SELECT (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) day# FROM DUAL
CONNECT BY (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) <=
TO_DATE ('20060830', 'YYYYMMDD'))
/
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= 100
/
20060730から20060830まで出力
SELECT (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) day#
FROM DUAL
CONNECT BY (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) <=
TO_DATE ('20060830', 'YYYYMMDD')
/
或は
SELECT *
FROM (SELECT (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) day# FROM DUAL
CONNECT BY (TO_DATE ('20060730', 'YYYYMMDD') + LEVEL - 1) <=
TO_DATE ('20060830', 'YYYYMMDD'))
/
SQLTIP--first、lastの利用
SELECT MAX (ename) KEEP (DENSE_RANK FIRST ORDER BY sal DESC) ename, deptno,
MAX (sal) sal
FROM emp
GROUP BY deptno
SELECT MAX (ename) KEEP (DENSE_RANK LAST ORDER BY sal) ename, deptno,
MAX (sal) sal
FROM emp
GROUP BY deptno
MAX (sal) sal
FROM emp
GROUP BY deptno
SELECT MAX (ename) KEEP (DENSE_RANK LAST ORDER BY sal) ename, deptno,
MAX (sal) sal
FROM emp
GROUP BY deptno
SQLTIP--LOTO 6番号生成
SELECT MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 1, num)) no1,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 2, num)) no2,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 3, num)) no3,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 4, num)) no4,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 5, num)) no5,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 6, num)) no6
FROM (SELECT grp, num
FROM (SELECT grp, num, MOD (ROWNUM - 1, 45) + 1 rnum
FROM (SELECT CEIL (LEVEL / 45) grp,
MOD (LEVEL - 1, 45) + 1 num
FROM DUAL
CONNECT BY LEVEL <= 45 * 10
ORDER BY 1, DBMS_RANDOM.VALUE))
WHERE rnum <= 6
ORDER BY grp, num)
GROUP BY grp
/
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 2, num)) no2,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 3, num)) no3,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 4, num)) no4,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 5, num)) no5,
MIN (DECODE (MOD (ROWNUM - 1, 6) + 1, 6, num)) no6
FROM (SELECT grp, num
FROM (SELECT grp, num, MOD (ROWNUM - 1, 45) + 1 rnum
FROM (SELECT CEIL (LEVEL / 45) grp,
MOD (LEVEL - 1, 45) + 1 num
FROM DUAL
CONNECT BY LEVEL <= 45 * 10
ORDER BY 1, DBMS_RANDOM.VALUE))
WHERE rnum <= 6
ORDER BY grp, num)
GROUP BY grp
/
SQLTIP--文字列から単語の数を計算
SELECT
(LENGTH ('THIS IS TEST STRING')
- LENGTH (REPLACE ('THIS IS TEST STRING', 'IS'))
)
/ LENGTH ('IS') cnt
FROM DUAL
/
(LENGTH ('THIS IS TEST STRING')
- LENGTH (REPLACE ('THIS IS TEST STRING', 'IS'))
)
/ LENGTH ('IS') cnt
FROM DUAL
/
SQLTIP--文字列分割
123,11,4567,8,99999,000,123456
「,」で分割
123
11
4567
...
...
SELECT SUBSTR (aa,
INSTR (aa, ',', 1, LEVEL) + 1,
INSTR (aa, ',', 1, LEVEL + 1) - INSTR (aa, ',', 1, LEVEL)
- 1
) sub
FROM (SELECT ',' || '123,11,4567,8,99999,000,123456' || ',' aa
FROM DUAL)
CONNECT BY LEVEL <= LENGTH (aa) - LENGTH (REPLACE (aa, ',')) - 1
2)
区分記号が2バイト以上の場合
SELECT SUBSTR (str,
INSTR (str, base, 1, LEVEL) + len,
INSTR (str, base, 1, LEVEL + 1)
- INSTR (str, base, 1, LEVEL)
- len
) sub
FROM (SELECT '#&' base, '#&' || '1#&(#&・#&?' || '#&' str,
LENGTH ('#&') len
FROM DUAL)
CONNECT BY LEVEL <= (LENGTH (str) - LENGTH (REPLACE (str, base))) / len - 1
3)
複数の行が存在する場合は
COL1
--------------------------------------------------
1/2/3
44/555
3/77
8/77/8
「/」 による分割
1
2
3
44
555
3
77
8
77
8
SELECT sub
FROM (SELECT DISTINCT rn, LEVEL,
SUBSTR (str,
INSTR (str, base, 1, LEVEL) + len,
INSTR (str, base, 1, LEVEL + 1)
- INSTR (str, base, 1, LEVEL)
- len
) sub
FROM (SELECT ROWNUM rn, '/' base, '/' || col1 || '/' str,
LENGTH ('/') len
FROM tab2)
CONNECT BY LEVEL <=
(LENGTH (str) - LENGTH (REPLACE (str, base)))
/ len
- 1)
「,」で分割
123
11
4567
...
...
SELECT SUBSTR (aa,
INSTR (aa, ',', 1, LEVEL) + 1,
INSTR (aa, ',', 1, LEVEL + 1) - INSTR (aa, ',', 1, LEVEL)
- 1
) sub
FROM (SELECT ',' || '123,11,4567,8,99999,000,123456' || ',' aa
FROM DUAL)
CONNECT BY LEVEL <= LENGTH (aa) - LENGTH (REPLACE (aa, ',')) - 1
2)
区分記号が2バイト以上の場合
SELECT SUBSTR (str,
INSTR (str, base, 1, LEVEL) + len,
INSTR (str, base, 1, LEVEL + 1)
- INSTR (str, base, 1, LEVEL)
- len
) sub
FROM (SELECT '#&' base, '#&' || '1#&(#&・#&?' || '#&' str,
LENGTH ('#&') len
FROM DUAL)
CONNECT BY LEVEL <= (LENGTH (str) - LENGTH (REPLACE (str, base))) / len - 1
3)
複数の行が存在する場合は
COL1
--------------------------------------------------
1/2/3
44/555
3/77
8/77/8
「/」 による分割
1
2
3
44
555
3
77
8
77
8
SELECT sub
FROM (SELECT DISTINCT rn, LEVEL,
SUBSTR (str,
INSTR (str, base, 1, LEVEL) + len,
INSTR (str, base, 1, LEVEL + 1)
- INSTR (str, base, 1, LEVEL)
- len
) sub
FROM (SELECT ROWNUM rn, '/' base, '/' || col1 || '/' str,
LENGTH ('/') len
FROM tab2)
CONNECT BY LEVEL <=
(LENGTH (str) - LENGTH (REPLACE (str, base)))
/ len
- 1)
SQLTIP--10進数から2進数へ、2進数から10進数へ
-- 10進数から 2進数へ
SELECT REPLACE (MAX (SYS_CONNECT_BY_PATH (bit, ',')), ',') bin
FROM (SELECT COUNT (*) OVER () - LEVEL + 1 level#,
DECODE (TRUNC (deci / POWER (2, LEVEL)),
ROUND (deci / POWER (2, LEVEL)), 0,
1
) bit
FROM (SELECT 699 deci
FROM DUAL)
CONNECT BY POWER (2, LEVEL - 1) <= deci)
START WITH level# = 1
CONNECT BY PRIOR level# = level# - 1
/
-- 2進数から 10進数へ
SELECT SUM (SUBSTR (bin, LEVEL, 1) * POWER (2, LENGTH (bin) - LEVEL)) deci
FROM (SELECT 11101 bin
FROM DUAL)
CONNECT BY LEVEL <= LENGTH (bin)
/
SELECT REPLACE (MAX (SYS_CONNECT_BY_PATH (bit, ',')), ',') bin
FROM (SELECT COUNT (*) OVER () - LEVEL + 1 level#,
DECODE (TRUNC (deci / POWER (2, LEVEL)),
ROUND (deci / POWER (2, LEVEL)), 0,
1
) bit
FROM (SELECT 699 deci
FROM DUAL)
CONNECT BY POWER (2, LEVEL - 1) <= deci)
START WITH level# = 1
CONNECT BY PRIOR level# = level# - 1
/
-- 2進数から 10進数へ
SELECT SUM (SUBSTR (bin, LEVEL, 1) * POWER (2, LENGTH (bin) - LEVEL)) deci
FROM (SELECT 11101 bin
FROM DUAL)
CONNECT BY LEVEL <= LENGTH (bin)
/
SQLTIP--カレンダー生成
--------------------------------------
SELECT MIN (DECODE (TO_CHAR (days, 'd'), 1, TO_CHAR (days, 'fmdd'))) 日,
MIN (DECODE (TO_CHAR (days, 'd'), 2, TO_CHAR (days, 'fmdd'))) 月,
MIN (DECODE (TO_CHAR (days, 'd'), 3, TO_CHAR (days, 'fmdd'))) 火,
MIN (DECODE (TO_CHAR (days, 'd'), 4, TO_CHAR (days, 'fmdd'))) 水,
MIN (DECODE (TO_CHAR (days, 'd'), 5, TO_CHAR (days, 'fmdd'))) 木,
MIN (DECODE (TO_CHAR (days, 'd'), 6, TO_CHAR (days, 'fmdd'))) 金,
MIN (DECODE (TO_CHAR (days, 'd'), 7, TO_CHAR (days, 'fmdd'))) 土
FROM (SELECT base_mon + LEVEL - 1 days,
( TRUNC (base_mon + LEVEL - 1, 'd')
- TRUNC (TRUNC (base_mon + LEVEL - 1, 'y'), 'd')
) / 7 + 1 week_grp
FROM (SELECT TO_DATE ('200605', 'yyyymm') base_mon
FROM DUAL)
CONNECT BY base_mon + LEVEL - 1 <= LAST_DAY (base_mon))
GROUP BY week_grp
ORDER BY week_grp
;
月 火 水 木 金 土 日
-- -- -- -- -- -- --
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
SELECT MIN (DECODE (TO_CHAR (days, 'd'), 1, TO_CHAR (days, 'fmdd'))) 日,
MIN (DECODE (TO_CHAR (days, 'd'), 2, TO_CHAR (days, 'fmdd'))) 月,
MIN (DECODE (TO_CHAR (days, 'd'), 3, TO_CHAR (days, 'fmdd'))) 火,
MIN (DECODE (TO_CHAR (days, 'd'), 4, TO_CHAR (days, 'fmdd'))) 水,
MIN (DECODE (TO_CHAR (days, 'd'), 5, TO_CHAR (days, 'fmdd'))) 木,
MIN (DECODE (TO_CHAR (days, 'd'), 6, TO_CHAR (days, 'fmdd'))) 金,
MIN (DECODE (TO_CHAR (days, 'd'), 7, TO_CHAR (days, 'fmdd'))) 土
FROM (SELECT base_mon + LEVEL - 1 days,
( TRUNC (base_mon + LEVEL - 1, 'd')
- TRUNC (TRUNC (base_mon + LEVEL - 1, 'y'), 'd')
) / 7 + 1 week_grp
FROM (SELECT TO_DATE ('200605', 'yyyymm') base_mon
FROM DUAL)
CONNECT BY base_mon + LEVEL - 1 <= LAST_DAY (base_mon))
GROUP BY week_grp
ORDER BY week_grp
;
月 火 水 木 金 土 日
-- -- -- -- -- -- --
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
登録:
投稿 (Atom)