/// BANGBOO BLOG ///

  • 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

November 16, 2009

Ora Ora Ora Ora Ora

おっすオラ藹??れ易いルール、無饅??無饅??無饅??無饅??無饅??無饅??ッ

■DML
DB製品豈?縺?nullの扱いを事前に調べる(word != ‘検索蛟?'やword = nullで縺?nullにヒットしない、is not nullを使う等)

null値はもっとも蟆?さな値、or大きな値・??nullが含まれるかnullの件数を先に確認してお縺?、下に臀??を載せた)
集計関数縺?NULLを無鐔??する(下に臀??を載せた)

文字列縺?'で囲む
藹??得したいカラムは集計関数に使繧?れるカラムを除いて全縺?GroupBy句に入れる
集計関数の条件縺?having句を使用する(where句は元のデータに対するも縺?)、having句には集計関数が入る(下に臀??を載せた)
SQLワイルドカード:複数文字%,1文字_
WINワイルドカード:複数文字*,1文字?
エスケープ文字縺?escape句で設定。like句の藹??ろにつ縺?。escape '\'
日臀??と文字列の藹??觸??が必要To_char関数縺?To_date関数を使用する
to_char(column,'yyyy/mm/dd hh24:mi:ss')
to_date('2009/02/21','yyyy/mm/dd')
横藹??を大き縺?するset line 150
縦を大き縺?するset pages 30
union縺?distinctが觸??かる、全藹??得縺?union all
inner join onは両方のテーブルにあるものだけ、どちらかだけにあるのは無縺?なるイメー繧?
left (outer) join onは左側のテーブルにしかないものも表示、左に右の該当部を縺?っつけるイメー繧?
right (outer) join onは右側のテーブルにしかないものも表示、右に左の該当部を縺?っつけるイメー繧?
full outer join onは全ての鐔??を表示

trancateは饅??速だがロールバックできない、deleteはロールバックできる、論理削除がindexメンテコスト菴?で良い
多対藹??縺?SQLが含まれないか確鐔??する(下に臀??を載せた)

■テーブル軆??合4遞?
1蟇?1、1対藹??の軆??合を行う
1対藹??でも行数が増えるが、多対藹??は全軆??合せになり行数が比例関数的に藹??えてしまう
多対藹??になるのはテーブル設計が悪いのでは・??
1)inner join - on () 両方あるものを表示、欠けがでる
2)left outer join - on () どちらかは觸??けがなく表示
3)right outer join - on ()  どちらかは觸??けがなく表示
4)full outer join - on ()  欠けがなく表示

select URIID,NAME,UKYAKUID from URIAGE left outer join TORIHIKI
 on (URIAGE.UKYAKUID = TORIHIKI.ID)
select URIID,NAME,UKYAKUID from TORIHIKI right outer join URIAGE
 on (URIAGE.UKYAKUID = TORIHIKI.ID)
select URIID,NAME,UKYAKUID from TORIHIKI full outer join URIAGE
 on (URIAGE.UKYAKUID = TORIHIKI.ID)
select 伝票番藹??,行番藹??,処理譌?,商品名,担当者名,顧客名,数驥? from 売臀??デー繧?
 left outer join 商品マス繧? on 売臀??デー繧?.商品ID = 商品マス繧?.商品ID
 left outer join 担当者マス繧? on 売臀??デー繧?.担当者ID = 担当者マス繧?.担当者ID
 left outer join 顧客マス繧? on 売臀??デー繧?.顧客ID = 顧客マス繧?.顧客ID
 order by 伝票番藹??,行番藹??

■なおjoin on藹?? 縺? where句での軆??合の違い
1)select * from A, B where A.a = B.a and A.c = 3;
2)select * from A inner join B on A.a = B.a where A.c = 3;
両者は同じ結果、前者の方が古縺?からある構文,後者が新しい構文。だがOuter joinは臀??記にある通り違う
https://okwave.jp/qa/q8090979.html

■WHERE縺?JOIN ONで条件を指定した場合の違い
SELECT * FROM movies LEFT OUTER JOIN counts ON counts.movie_id = movies.id WHERE counts.date_at = '2012-12-16';
 WHERE句縺?JOINが終繧?ってから評価される→Outer joinでも12/16でない映画が含まれずLEFTが欠ける
この問題の解決に縺?WHERE句に条件を指定するのでな縺?JOIN ONの追加条件として指定する
SELECT * FROM movies LEFT OUTER JOIN counts ON counts.movie_id = movies.id AND counts.date_at = '2012-12-16';
 Outer joinしLEFTの全映画が出力したいので、結合前縺?12/16以藹??のカウントを外した上で軆??合させると逆縺?LEFT側は全部でる(RIGHTの条件で軆??った上縺?LEFT OUTER JOINだ縺?RIGHTがNULLでもLEFTが出る)
http://hakutoitoi.hatenablog.com/entry/2012/12/17/005208

■多対藹??、1対藹??の鐔??謨?
社員と職域、社員と手当、それぞれ結合しても多の鐔??謨?(1x多)になる
こんな設計や操作はするなという事(多x多の鐔??数になる、多対藹??の軆??合は鐔??繧?ないこと・??
-- データ挿入・??社蜩?
INSERT INTO x_employee (no,name) VALUES (1, '田中');
INSERT INTO x_employee (no,name) VALUES (2, '鈴譛?');
INSERT INTO x_employee (no,name) VALUES (3, '佐阯?');
-- データ挿入・??職域(兼任が発生)
INSERT INTO x_joblevel (no,res) VALUES (1, '部髟?');
INSERT INTO x_joblevel (no,res) VALUES (1, '課髟?');
INSERT INTO x_joblevel (no,res) VALUES (2, '蟷?');
-- データ挿入・??手当(一人に幾つか付縺?)
INSERT INTO x_compensation (no,allow) VALUES (1, '住宅');
INSERT INTO x_compensation (no,allow) VALUES (1, '交通');
INSERT INTO x_compensation (no,allow) VALUES (2, '住宅');
-- 1対藹??(田中が兼任のため田中分が2行、鈴譛?1行で都合3行、1対藹??だとまだ兼任と理解ができる)
select * from x_employee
 inner join x_joblevel on x_employee.no = x_joblevel.no
-- 多対藹??(田中兼任2行x田中手当2行の藹??計4行、鈴木縺?1行で都合5行、田中だけ縺?4行でるとマトリックスの諢?味が不譏?になる)
select * from x_employee
 inner join x_joblevel on x_employee.no = x_joblevel.no
 inner join x_compensation on x_employee.no = x_compensation.no

■Group by/having/where
藹??得したいカラムは集計関数に使繧?れるカラムを除いて全縺?GroupBy句に入れるの臀??
select distinct boss from fun_test_data
select department, avg(salary) from fun_test_data group by department
select boss, avg(salary) from fun_test_data group by boss
select department, boss, avg(salary) from fun_test_data group by department, boss

集計関数の条件縺?having句を使用する(where句は元のデータに対するも縺?)、having句には集計関数が入る例
select department, count(department), avg(salary) from fun_test_data where department!="営業" group by department;
select department, count(department), avg(salary) from fun_test_data where department!="営業" group by department having avg(salary) > 45;
窶?moreにデータをDDLを置いてお縺?ので操作して感じる

集計関数に縺?sum() count() avg() stddev()標準偏蟾? variance()分謨?etc..がある

nullを無鐔??するので、3件が100, null, 200のとき平均縺?150となる、nullを0にする事
SELECT AVG(NVL(SURYO,0)) AS 平均, COUNT(NVL(SURYO,0)) AS 件謨? FROM TEST1

data2縺?nullがありカウントしようとするがnullはカウントされず1行目はダメ、件数縺?keyをカウントせよ
select COUNT(DATA2) from EXAMPLE_TABLE where DATA2 is NULL
select COUNT(ID) from EXAMPLE_TABLE where DATA2 is NULL

窶?SQLはバグかどうか分からず失敗かどうか分かりに縺?い→計算蠑?を書いてからSQLを書縺?
集計値の集計を行う際には集計順蠎?に注諢?せよ | 実践から学ぶ分析の落とし遨? - GiXo Ltd.

■サブクエリ・??副蝠?い合繧?せ)
どこでもOK、any() in() some() exists() not exists()等がある、mysqlに縺?minus() except()はない

/// where条件が1莉?
SELECT 藹??注番藹?? FROM 藹??注表 WHERE 商品コード = (SELECT 商品コード FROM 商品陦? WHERE 商品名 = 'JUICE');
/// where条件が複謨?
SELECT 藹??注番藹?? FROM 藹??注表 WHERE 商品コード IN (SELECT 商品コード FROM 商品陦? WHERE 単萓? = 400);
/// having縺?
SELECT 顧客コード,COUNT(DISTINCT 藹??注番藹??) FROM 藹??注表 GROUP BY 顧客コード HAVING 藹??注個謨? < (SELECT MIN(藹??注個謨?) FROM 藹??注表 WHERE 顧客コード = '002');
/// from縺?
SELECT MAX(AVG_J) AS MAX_AVG FROM (SELECT AVG(藹??注個謨?) AS AVG_J FROM 藹??注表 GROUP BY 顧客コード) ;
/// selectに・??出力表のカラム数縺?1個だけで、これが変繧?る等はできないかと・??
SELECT 顧客コード,AVG(藹??注個謨?), (SELECT AVG(藹??注個謨?) FROM 藹??注表) FROM 藹??注表 GROUP BY 顧客コード;

selectサブクエリにカラムを一つづつ足せば鐔??数も可だが
select name, res,
 (select allow from x_compensation where x_compensation.no = x_employee.no limit 0, 1),
 (select allow from x_compensation where x_compensation.no = x_employee.no limit 1, 1)
 from x_employee inner join x_joblevel on x_employee.no = x_joblevel.no inner join x_compensation on x_employee.no = x_compensation.no

/// 相関サブクエリ・??出力表のカラム数が変繧?る等はできないかと・??
メインクエリの鐔??ごとにサブクエリを実行、結合をサブに鐔??入している、違う書き方ができるかも知れないがサブからでな縺?メインから考えている感じ
例1)
SELECT * FROM 商品陦? AA WHERE '20010401' IN  (SELECT 納品譌? FROM 藹??注表 BB WHERE AA.商品コード = BB.商品コード);
例2)
SELECT SUM(藹??注個謨?),納品譌? FROM 藹??注表 PP GROUP BY 納品譌? HAVING SUM(藹??注個謨?) > (SELECT 150 + MAX(藹??注個謨?) FROM 藹??注表 QQ WHERE PP.納品譌? = QQ.納品譌?);

■Union
UNION句でマージする複数縺?SELECT文は、(1)SELECT句のカラム数が同じこ縺?(2)カラムのデータ型が同じか、変觸??可能であるこ縺?
select shit from ass union all select kuso from ketsu

■SQLはカラム数の藹??加数で觸??成考える?
left outer joinはカラム数がカラム数の合計から共通縺?join onのカラム数を引いた数・??行数は同じ)
 full outer join はカラム数がカラム数の合計から共通縺?join onのカラム数を引いた数・??行数縺?leftの鐔??素数縺?rightの鐔??素数を合計したもの・??
unionは重複を除藹??し表を足し合繧?せるため行数が両表の合計行数・??カラム数は合致藹??要でカラム数は藹??繧?らない)
unian allは重複を除藹??せず表を足し合繧?せるため行数が両表の合計行数・??カラム数は合致藹??要でカラム数は藹??繧?らない)
cross joinはカラム数が両表のカラム数の合計、行数は両表の鐔??数の觸??け算
 再帰的縺?SQL処理縺?cross joinし条件を付けるか?
  標準SQL縺?From句のカンマ縺?cross joinとなる
with句は副蝠?い合繧?せを見やす縺?したも縺?
distinct縺?(組み合繧?せ縺?)一諢?になる行のみにし重複を省縺?
UNION 縺?UNION ALLの違い - Qiita
CROSS JOIN (クロス軆??合)を使ってデータを藹??得する - JOIN (結合)を使いこなそう - SQL Server 入門 (sql55.com)
SQL縺?DISTINCTとは・??(OracleやMySQLで使用する方觸??) | IT職種コラム (it-kyujin.jp)

■テーブル設計、制軆??
CONSTRAINT pk_uriage PRIMARY KEY (伝票番藹??, 行番藹??),
CONSTRAINT fk_shohin FOREIGN KEY (商品ID) REFERENCES 商品マス繧?(商品ID)
CONSTRAINT ck_gender CHECK (性蛻?=0 OR 性蛻?=1)
制軆??は列に指定しても、うしろで指定してもどちらでもよい
CONSTRAINTのキー名を省略するとオラクルが勝手につける
主キーに縺?NULLは入らない
ユニークキーに縺?NULLを入れてもよい
NOT NULLの未入力はエラ繝?

■シーケン繧?
シーケンスはオブジェクトとして表とは別に臀??成する
デクリメントはできないので修正縺?DROPして臀??成し直す
DUALはダミー表
nextvalはインクリした後の蛟?
currvalは現在蝨?
create sequence testseq
select testseq.nextval from dual
select testseq.currval from dual
insert into URIAGE (URIID,URIDATE,UKYAKUID) values (testseq.nextval,'09-11-16','101')
drop sequence testseq

■ビュ繝?
頻軆??に鐔??繧?れるような蝠?い合繧?せをスキーマに格軆??してお縺?、パフォーマンスが上がる場合がある
集約等をしなければパフォーマンスには問題がない。次を使うとパフォーマンスが落ちる。OLAP 関数・??RANK, DENSE_RANK, ROW_NUMBER 等)、集約関数・??AVG, COUNT, SUM, MIN, MAX)、集合演算子( UNION, INTERSECT, EXCEPT 等 )
ビューは觸??索だけでな縺?、データの追加、更新、削除も行える※使用しない方が良い?
create view 売臀??ビュ繝? as
 select 伝票番藹??,行番藹??,処理譌?,商品名,担当者名,顧客名,数驥? from 売臀??デー繧?
 left outer join 商品マス繧? on 売臀??デー繧?.商品ID = 商品マス繧?.商品ID
 left outer join 担当者マス繧? on 売臀??デー繧?.担当者ID = 担当者マス繧?.担当者ID
 left outer join 顧客マス繧? on 売臀??デー繧?.顧客ID = 顧客マス繧?.顧客ID
 order by 伝票番藹??,行番藹??
select * from 売臀??ビュ繝?

■用鐔??
concat()窶?CONCATENATE 文字連軆??
coalesce()…コーレス、合体する、荳?えられた引数のう縺?NULLでない最初の藹??数を返す
LPAD() RPAD()…文字の右詰左詰め
OLAP窶?OnLine Analytical Processing=分析、キューブ

■インデック繧?
1)インデックスが効かない
関数 where datediff(now(),mod_date)>180
蠑? where col1 / 2 = 0
否藹??構文 where col1 != 3
Like検索・??前方臀??致除く) where col1 like '%string%'とかwhere col1 like '%string'とか
2)複合インデックスでは指定順が重要
index a
 create index idxA1 on tbl (col1);
 create index idxA2 on tbl (col2);
 -> where col1 = x > idxA1が使用される
 -> where col2 = x > idxA2が使用される
 -> where col1 = x AND col2 = x > idxA1か2のどちらかが使用される
index b
 create index idxB1 on tbl (col1, col2);
 -> where col1 = x > idxB1が使用される
 -> where col2 = x > インデックスは使用されない
 -> where col1 = x AND col2 = x > idxB1が使用される,indexA1,A2より高速
index c
 create index idxC1 on tbl (col2, col1);
 -> where col1 = x > インデックスは使用されない
 -> where col2 = x > idxC1が使用される
 -> where col1 = x AND col2 = x > idxC1が使用される,indexA1,A2より高速

■RFM(recency frequenctry monetary)
SELECT name, MAX(date), MIN(date) FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no GROUP BY name ORDER BY MAX(date) DESC
SELECT name, count(x_bill.no) FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no GROUP BY name ORDER BY count(date) DESC
SELECT name, sum(total_bill) FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no  GROUP BY name ORDER BY sum(total_bill)  DESC
SELECT name, SUM(price * unit) FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no RIGHT JOIN x_purchase ON x_bill.no = x_purchase.p_no GROUP BY name ORDER BY SUM(price * unit) DESC

SELECT name, MAX(date), count(DISTINCT x_bill.no), SUM(price * unit) FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no RIGHT JOIN x_purchase ON x_bill.no = x_purchase.p_no GROUP BY name ORDER BY SUM(price * unit) DESC
 ※購入頻度は藹??対藹??で重複が出るのでカウント縺?distinct primaryKeyで重複を含めない

↓順位を点数化のため、MySQLに縺?Rownumがなく変数を使いシンプルな表でまず作った
SET @rownum_recent=0; 
SELECT @rownum_recent:=@rownum_recent+1 as rank_recent, no, name, recent  from
 (SELECT x_employee.no, name, MAX(date) as recent FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no GROUP BY name ORDER BY MAX(date) DESC) as t1

SET @rownum_frequent=0; 
SELECT @rownum_frequent:=@rownum_frequent+1 as rank_frequent, no, name, frequent from
 (SELECT x_employee.no, name, count(x_bill.no) as frequent FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no GROUP BY name ORDER BY count(date) DESC) as t2

SET @rownum_money=0; 
SELECT @rownum_money:=@rownum_money+1 as rank_money, no, name, money from
 (SELECT x_employee.no, name, SUM(price * unit) as money FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no RIGHT JOIN x_purchase ON x_bill.no = x_purchase.p_no GROUP BY name ORDER BY SUM(price * unit) DESC) as t3

↓まとめる(user_noで軆??合した、別名を付ける計算カラムよりどの元の表かが重要かもLeftかRight joinか縺?)

SET @rownum_rank=0;
SET @rownum_recent=0;
SET @rownum_frequent=0;
SET @rownum_money=0;

SELECT @rownum_rank:=@rownum_rank+1 as rank, rank_recent+rank_frequent+rank_money as least_score_wins, t1_r.no as user_no, t1_r.name, recent, frequent, money, rank_recent, rank_frequent, rank_money
FROM (
   SELECT @rownum_recent:=@rownum_recent+1 as rank_recent, t1.no, t1.name, recent
   FROM (SELECT x_employee.no, x_employee.name, MAX(date) as recent FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no RIGHT JOIN x_purchase ON x_bill.no = x_purchase.p_no GROUP BY x_employee.no, x_employee.name ORDER BY MAX(date) DESC) as t1
) as t1_r
LEFT OUTER JOIN (
   SELECT @rownum_frequent:=@rownum_frequent+1 as rank_frequent, t2.user_no, t2.name, frequent
   FROM (SELECT x_bill.user_no, x_employee.name, count(distinct x_bill.no) as frequent FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no RIGHT JOIN x_purchase ON x_bill.no = x_purchase.p_no GROUP BY x_bill.user_no, x_employee.name ORDER BY count(distinct x_bill.no) DESC) as t2
) as t2_f
ON t1_r.no = t2_f.user_no
LEFT OUTER JOIN (
   SELECT @rownum_money:=@rownum_money+1 as rank_money, t3.no, t3.name, money
   FROM (SELECT x_employee.no, x_employee.name, SUM(price * unit) as money FROM x_employee RIGHT JOIN x_bill ON x_employee.no = x_bill.user_no RIGHT JOIN x_purchase ON x_bill.no = x_purchase.p_no GROUP BY x_employee.no, x_employee.name ORDER BY SUM(price * unit) DESC) as t3
) as t3_m
ON t2_f.user_no = t3_m.no
ORDER BY least_score_wins asc

■NULLの件数を事前に数えてお縺?
SELECT *
 FROM (SELECT 'value', count(COALESCE(value,0))  FROM bangboo_data.x_data WHERE value IS NULL)
 union all
 (SELECT 'value2', count(COALESCE(value2,0))  FROM bangboo_data.x_data WHERE value2 IS NULL)
 union all
 (SELECT 'v_no_null', count(COALESCE(v_no_null,0))  FROM bangboo_data.x_data WHERE v_no_null IS NULL)
↑が安全軆??

SELECT count_null_1, count_null_2
 FROM (SELECT value, count(COALESCE(value,'')) as count_null_1 FROM x_data WHERE value IS NULL GROUP BY value) as t1,
 (SELECT value2, count(COALESCE(value2,''))  as count_null_2 FROM x_data WHERE value2 IS NULL GROUP BY value2) as t2
 窶?From A, B, C でクロス軆??合となり全軆??み合繧?せがでる、1行ずつならOKだが、、
 窶?SQLはカウント0件をグルーピングできない、表示自臀??存在しないことになるから、↑は藹??々危険で↓縺?
SELECT count_null_1, count_null_2
 FROM (SELECT count(COALESCE(value,'')) as count_null_1 FROM x_data WHERE value IS NULL) as t1,
 (SELECT count(COALESCE(value2,''))  as count_null_2 FROM x_data WHERE value2 IS NULL) as t2,
 (SELECT count(COALESCE(v_no_null,0))  as count_null_3 FROM x_data WHERE v_no_null IS NULL) as t3

■SQL一隕?
 https://qiita.com/tatsuya4150/items/69c2c9d318e5b93e6ccd
UPDATE テーブル名 SET カラム名 = 蛟?, カラム名 = 蛟?  WHERE id = 1
INSERT INTO テーブル名 VALUES ('1')DELETE FROM テーブル名 WHERE 条件
intersectは重複するもの SELECT name FROM ユーザー・?? INTERSECT SELECT name FROM ユーザ繝?2
 窶?unionは和集合、exceptは差集合、intersectは軆??集合


twitter
Hatena
Google Buzz
newsing
Yahoo!
Buzzurl
Technorati
del.icio.us
Choix
Iza!
Livedoor Clip
Facebook
Evernote
 

Posted by funa : 06:54 PM | Web | Comment (0) | Trackback (0)