買った書籍 独習C# 新版 |Excel VBA逆引き辞典パーフェクト 第3版 |SQLアンチパターン|確かな力が身につくC#「超」入門
C#は会社で新しい環境の開発をすることになるかもしれず、また覚えなくては。
昔Unityで使ったけど単なる関数を作るレベルでしか使っていない。
C#の基礎だけ学んでも使えるようにはならないのでUnityがC#を使うので自宅でゲームを作ってみるか。
買った書籍 独習C# 新版 |Excel VBA逆引き辞典パーフェクト 第3版 |SQLアンチパターン|確かな力が身につくC#「超」入門
C#は会社で新しい環境の開発をすることになるかもしれず、また覚えなくては。
昔Unityで使ったけど単なる関数を作るレベルでしか使っていない。
C#の基礎だけ学んでも使えるようにはならないのでUnityがC#を使うので自宅でゲームを作ってみるか。
購入した書籍コミック ビッグデータ分析・活用のためのSQLレシピ
マイナビ出版
続きを読む
購入明細テーブルで顧客の古い履歴を求める
P202_SQL実践入門_購入明細で顧客の古い履歴を求める
続きを読む
P277_SQL実践入門_前日の株価と比較して上下を示す
株価を前日と比較して上下同じを示す
考え方はSELECT句にSELECT句を入れて全体の出力に合わせて比較するというC言語でループを考えている人にとっては理解に苦しむSQLクエリである。
ぐるぐる回すループを使わなくてもSELECTでループみたいなことができることを示した例。
基本のテーブル
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 32 33 34 35 36 37 38 39 40 41 42 43 44 |
/* 日付で比較して、 */ CREATE TABLE Stocks( brand VARCHAR(8) NOT NULL, sale_date DATE NOT NULL, price INT NOT NULL, --CONSTRAINT pk_Stocks Primary key(sale_date) ) INSERT INTO Stocks VALUES('A鉄鋼','2008-07-01',1000), ('A鉄鋼','2008-07-04',1200), ('A鉄鋼','2008-08-12',800), ('B商社','2008-06-04',3000), ('B商社','2008-12-31',3000), ('C電気','2008-07-01',9000), ('D産業','2008-06-04',5000), ('D産業','2008-06-05',5000), ('D産業','2008-06-06',4800), ('D産業','2008-12-01',5100) SELECT brand,sale_date,price, CASE SIGN(price - ( SELECT price FROM Stocks S1 WHERE brand = Stocks.brand AND sale_date = (SELECT MAX(sale_date) FROM Stocks S2 WHERE brand = Stocks.brand AND sale_date< Stocks.sale_date ) ) ) WHEN -1 THEN '↓' WHEN 0 THEN '→' WHEN 1 THEN '↑' END FROM Stocks --drop Table Stocks |
1 2 3 4 5 |
--分解して、同じテーブル同士で比較する SELECT * FROM Stocks S2 inner JOIn Stocks S ON S2.brand = S.brand AND S2.sale_date< S.sale_date |
1 2 3 4 5 6 7 8 |
--Sの最大日がでるが1件のみ SELECT MAX(S.sale_date) FROM Stocks S2 inner JOIn Stocks S ON S2.brand = S.brand AND S2.sale_date< S.sale_date --Sの最大日がでるので、会社でまとめると会社分が出力される。ただし、同日はでない --同日が存在する場合はS2.sale_date<= S.sale_dateにする |
ただし同日は指定していないので、同日は<=としる
1 2 3 4 5 |
SELECT MAX(S.sale_date) FROM Stocks S2 inner JOIn Stocks S ON S2.brand = S.brand AND S2.sale_date < S.sale_date Group by S.brand--同日が存在する場合はS2.sale_date <= S.sale_dateにする |
1 2 3 4 5 6 7 8 |
--S1とS2 でそれぞれ最大日がでる SELECT MAX(S1.sale_date) ,MAX(S2.sale_date) FROM Stocks as S1 CROSS JOIN Stocks as S2 WHERE S1.brand = S2.brand AND S1.sale_date < S2.sale_date--INNER JOINと同じ --DROP TABLE Stocks |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
--Stocks --3つのStocksを使っている。 --外側のSTocksと2つ目のStocksで日付を比べて --外側のStocksと1つ目のStocksで同じ日付で出力する SELECT brand,sale_date, (SELECT S1.sale_date FROM Stocks S1 WHERE S1.brand = Stocks.brand AND sale_date = --Stocks.sale_date (SELECT MAX(S2.sale_date) FROM Stocks S2 WHERE S2.brand = Stocks.brand AND S2.sale_date< Stocks.sale_date ) ) as s1_date FROM Stocks |
カラムの別名はよく使うけど、存在しない列をSELECT文で追加する
1 2 3 4 5 6 |
--テーブルに存在しない列を作ってデータを表示する SELECT 'test' as KAMEI--KAMEI列にtestというデータが表示される --この方法を使えば、テーブルの出力時にある条件下のデータとして区別できる ----student_idをidとして表示して、もとの列も含めて全部だす SELECT student_id as id,* FROM ScoreCols--student_idをidとして表示して、もとの列も含めて全部だす |
まとめ
(1)新規テーブルに別のテーブルのデータをコピーしたい
select * into newtable from table where (条件)
この場合、同じクエリを実行するとすでにnewtableがあるよエラーになるので初回だけ使える
つまり、すでにnewtableが存在するときは使えない。
CREATE TABLEをしなくてもnewtableが作成されるので手間を省ける
(2)すでに存在するテーブルに別のテーブルからコピーしたい
insert into anotherTable select 列 from table where (条件)
(例)INSERT INTO newMember SELECT * FROM Member
<(1)の場合の例>
Memberテーブルがあったとする(name,age,cityの列)
このテーブルと同じテーブルを作りたい。
使い方は、クエリを書いていて、他のクエリに改良したときに、出力内容が同じかを確かめたいときに、それぞれのクエリのSELECT出力を新しいテーブルに入れる。
そして、2つ(もしくは3つとか)のテーブルを下記のEXCEPTで比較して0件なら同じ出力と言える。
数百行程度なら出力内容をコピーしてエクセルに貼り付ければよいが、これが10万件とかだとエクセルに貼り付けて確認するのも面倒になる。
そこで、SQLManagementStudioで確認できればそれが早い
テーブルを作ってデータを入れて確認したいときに、いちいちCREATE TABLEして列と型を書いて、、、とするとイライラするので無駄な手順が省けると非常に助かる。
でも一部の列だけの情報がほしいときは結局はCREATE TABLEでテーブル定義必要だったりする。
member:もともとのテーブル
newmember:memberから新しいテーブルを作る
1 2 3 4 |
SELECT TOP 10 * FROM MEMBER SELECT * INTO newMember FROM Member--これでCREATE TABLEを実行しなくても newmemberテーブルが作成される。なおすでにテーブルが存在すると既にテーブルがあるよエラーになる。 --ただし、インデックスとかもろもろの設定はつかないのであくまでもデータを一時的に使いたいときに使うらしい select * FROM newMember |
[select * into newtable from table]はすでにテーブルが存在すると既にテーブルがあるよエラーになる。
–すでにテーブルが存在するときは
1 |
INSERT INTO newMember SELECT * FROM Member |
INSERT INTOを使う
すでにテーブルが存在するのにSELECT INTOを使うとエラーになる。
EXCEPTで差分を調べる。同じ列である必要がある
1 2 3 4 |
--EXCEPTで2つのテーブルの差を検索する。これで0件なら一致 SELECT * FROM Member EXCEPT SELECT * FROM newMember |
1 2 3 4 5 6 7 8 |
--LEFT OUTERで差分を調べる。NULLがあれば差がある SELECT * FROM Member LEFT OUTER JOIN newMember ON Member.name = newMember.Name SELECT * FROM Member LEFT OUTER JOIN newMember ON Member.name = newMember.Name WHERE Member.name IS NULL or Member.age IS NULL or Member.City IS NULL --0件ならさいがないと思う |
–NewMemberの一部を変更してみた
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
UPDATE newMember SET City = 'a' WHERE NAME = '坂本' AND Age = 19 AND City = '東京' select * from newMember /* Name Age City 坂本 19 a >>ここを変えた 中原 50 大阪 山岡 6 東京 赤橋 42 北海道 西 69 大阪 */ SELECT * FROM Member EXCEPT SELECT * FROM newMember /* 結果はmemberテーブルの坂本さんが違うと出力される Name Age City 坂本 19 東京 */ |
またテーブルのみならず
SELECTで出力した内容を挿入したいときは
–FROM のテーブルをSELECTで出力して新規テーブルに挿入する場合は別名にする
–別名にしないと警告が出る
1 2 3 |
SELECT * into tmp01 FROM ( SELECT * FROM Member WHERE Age > 20 ) as ab |
それか、一旦別のテーブルに入れてからさらに、SELECT INTOしてもよいかも
SQLパズルはクエリ、ストアドを作る人にとってヒントになる例題がてんこ盛りです。理解しにくい部分は実際に入力して出力して確認して自分で理解しましょう。
sqlの勉強 グループの中で連番になっていないデータやグループを探す方法を考え中
例えば
Aグループの中に複数のデータがありそのレコードの番号はグループごとに連番が割り振られる
ただしデータ削除でグループ内で連番の規則性が損なわれた
続きを読む
/*SQLのお勉強、グループごとにある最大値の行を取得する
参考サイト
https://qiita.com/nogitsune413/items/f413268d01b4ea2394b1
考え方は、グループの中で最大を取得する。しかしこのテーブルだけでは、
他の情報氏名が得られないので、もとのテーブルとINNERJOINをして得る
つまり2段階方式 続きを読む