|
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
Sub test() 'テーブル作成 -------------------------------------------------------- Set t = CurrentDb.CreateTableDef("ttest") Set f = t.CreateField("id", dbDate) t.Fields.Append f CurrentDb.TableDefs.Append t 'パススルークエリ作成 -------------------------------------------------------- 'SQLServerへ接続 queryName = "test" For i = 0 To CurrentDb.QueryDefs.Count - 1 If CurrentDb.QueryDefs(i).Name = queryName Then CurrentDb.QueryDefs.Delete queryName Next i Set t = CurrentDb.CreateQueryDef(queryName) With t .Connect = "ODBC; Driver=SQL Server; Server=ESPRIMO\SQLEXPRESS; Database=my_database" .ReturnsRecords = True .SQL = "SELECT * FROM tbl;" End With Set t = Nothing '更新系などのパススルークエリも作成できる -------------------------------------------------------- queryName = "test" For i = 0 To CurrentDb.QueryDefs.Count - 1 If CurrentDb.QueryDefs(i).Name = queryName Then CurrentDb.QueryDefs.Delete queryName Next i Set t = CurrentDb.CreateQueryDef(queryName) With t .Connect = "ODBC; Driver=SQL Server; Server=ESPRIMO\SQLEXPRESS;Database=my_database" .ReturnsRecords = False .SQL = "DELETE FROM tbl;" End With Set t = Nothing 'リンクテーブル(mdbへ接続) -------------------------------------------------------- Set t = CurrentDb.CreateTableDef("AccessLink") t.Connect = ";DATABASE=" & Application.CurrentProject.Path & "/tmp.mdb;" t.SourceTableName = "tbl" CurrentDb.TableDefs.Append t 'テーブル削除 -------------------------------------------------------- tableName = "test_tbl" For i = 0 To CurrentDb.TableDefs.Count - 1 If CurrentDb.TableDefs(i).Name = tableName Then CurrentDb.TableDefs.Delete tableName Exit For End If Next i 'クエリの実行 -------------------------------------------------------- 'new_tableを作成しold_tableのデータをnew_tableへ入れる。 CurrentDb.Execute "select * into new_table from old_table" 'new_tableにold_tableのデータを入れる。 CurrentDb.Execute "insert into new_table select * from old_table" End Sub |
VBA 農産物売上集計
mdbに登録する予定で作成していたが、途中でエクセルのみにしようと思い中断。
|
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
Sub auto_open() On Error Resume Next Application.CommandBars("cell").Controls("処理実行").Delete Application.CommandBars("cell").Controls("シート初期化(貼付前処理)").Delete With Application.CommandBars("cell").Controls.Add .FaceId = 18 .Caption = "シート初期化(貼付前処理)" .OnAction = "SheetsClear" End With With Application.CommandBars("cell").Controls.Add .FaceId = 18 .Caption = "処理実行" .OnAction = "MainProcedure" End With End Sub Sub auto_close() On Error Resume Next Application.CommandBars("cell").Controls("処理実行").Delete Application.CommandBars("cell").Controls("シート初期化(貼付前処理)").Delete End Sub Sub SheetsClear() Sheets("<実績表集計表>貼付1").Rows("1:1000").Delete Sheets("<実績表集計表>貼付2").Rows("1:1000").Delete Sheets("<買取業者別 手数料集計一覧表>貼付").Rows("1:1000").Delete End Sub Sub MainProcedure() On Error GoTo e YearMonth = InputBox("登録月をYYYY/MMの形式で入力してください。") YearMonth = StrConv(YearMonth, vbNarrow) YearMonth = YearMonth & "/01" If True = IsDate(YearMonth) Then yesno = MsgBox(Format(YearMonth, "yyyy年mm月") & "でよろしいですか?", vbYesNo) If yesno = vbNo Then Exit Sub Else MsgBox "正しい登録月を入力してください。" Exit Sub End If If False = DataUpload("<実績表集計表>貼付1", 1, YearMonth) Then GoTo e If False = DataUpload("<実績表集計表>貼付2", 1, YearMonth) Then GoTo e If False = DataUpload("<買取業者別 手数料集計一覧表>貼付", 2, YearMonth) Then GoTo e MsgBox "完了しました。" Exit Sub e: MsgBox "エラーが発生しています。" End Sub Function DataUpload(sheetName, sheetType, salesDate) On Error GoTo e Set con = CreateObject("adodb.connection") con.Open ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "/sales.mdb") Dim w As Worksheet: Set w = Sheets(sheetName) For r = 1 To w.UsedRange.Rows.Count If sheetType = 1 And _ w.Cells(r, 1).Text <> "" And IsNumeric(w.Cells(r, 1).Text) And _ w.Cells(r, 8).Text <> "" And IsNumeric(w.Cells(r, 8).Text) Then partnerCode = w.Cells(r, 1).Text partnerName = w.Cells(r, 2).Text salesVolume = w.Cells(r, 6).Text salesAmount = w.Cells(r, 7).Text marginCost = w.Cells(r, 10).Text pointCost = w.Cells(r, 18).Text overheadCost = w.Cells(r, 19).Text q = "insert into SalesTable (売上年月日,パートナーID,パートナー名称,売上数量,売上金額,手数料,ポイント負担額,諸経費,登録日時) " & _ "values (#" & salesDate & "#,'" & partnerCode & "','" & partnerName & "','" & salesVolume & "','" & salesAmount & "','" & marginCost & "','" & pointCost & "','" & overheadCost & "',#" & Now() & "#)" con.Execute q End If If sheetType = 2 And _ w.Cells(r, 1).Text <> "" And IsNumeric(w.Cells(r, 1).Text) And _ w.Cells(r, 4).Text <> "" And IsNumeric(w.Cells(r, 4).Text) Then partnerCode = w.Cells(r, 1).Text partnerName = w.Cells(r, 2).Text salesVolume = w.Cells(r, 4).Text salesAmount = w.Cells(r, 5).Text marginCost = w.Cells(r, 7).Text pointCost = w.Cells(r, 9).Text overheadCost = 0 q = "insert into SalesTable (売上年月日,パートナーID,パートナー名称,売上数量,売上金額,手数料,ポイント負担額,諸経費,登録日時) " & _ "values (#" & salesDate & "#,'" & partnerCode & "','" & partnerName & "','" & salesVolume & "','" & salesAmount & "','" & marginCost & "','" & pointCost & "','" & overheadCost & "',#" & Now() & "#)" con.Execute q End If Next r If con.State = 1 Then con.Close Set con = Nothing DataUpload = True Exit Function e: If con.State = 1 Then con.Close Set con = Nothing DataUpload = False End Function Sub MasterUpdate() On Error GoTo e Set con = CreateObject("adodb.connection") con.Open ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "/sales.mdb") q = "delete from MasterTable" con.Execute q Dim w As Worksheet: Set w = Sheets("マスタ") For r = 1 To w.UsedRange.Rows.Count If w.Cells(r, 1).Text <> "" And w.Cells(r, 2).Text <> "" And w.Cells(r, 3).Text <> "" Then Select Case w.Cells(r, 3).Text Case "正契約農産物", "準契約農産物", "委託農産物", "買取農産物", "花卉", "契約加工品", "委託加工品", "買取加工品" partnerCode = w.Cells(r, 1).Text partnerName = w.Cells(r, 2).Text partnerType = w.Cells(r, 3).Text q = "insert into MasterTable (パートナーID,パートナー名称,パートナータイプ,登録日時) " & _ "values ('" & partnerCode & "','" & partnerName & "','" & partnerType & "',#" & Now() & "#)" con.Execute q w.Rows(r).Columns("A:C").Interior.ColorIndex = 0 ' OKの場合 Case Else w.Cells(r, 3).Interior.Color = RGB(255, 0, 0) 'A:Cは空白ではないが、C列が不正 End Select Else w.Rows(r).Columns("A:C").Interior.Color = RGB(255, 0, 0) 'A:C列の何れか空白 End If Next r If con.State = 1 Then con.Close Set con = Nothing MsgBox "完了しました。" Exit Sub e: If con.State = 1 Then con.Close Set con = Nothing MsgBox "エラーが発生しています。" End Sub Sub DataDelte() On Error GoTo e Dim w As Worksheet: Set w = Sheets("表紙") yesno = MsgBox(w.Cells(6, 2).Text & "の日付で登録したデータは全て削除されます。よろしいですか?", vbYesNo) If yesno = vbNo Then Exit Sub Set con = CreateObject("adodb.connection") con.Open ("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "/sales.mdb") q = "delete from SalesTable where 売上年月日 = #" & w.Cells(6, 2).Text & "#" con.Execute q If con.State = 1 Then con.Close Set con = Nothing MsgBox "完了しました。" Exit Sub e: If con.State = 1 Then con.Close Set con = Nothing MsgBox "エラーが発生しています。" End Sub |
Excel 標準偏差、相関係数、線形回帰
標準偏差、相関係数、線形回帰の求め方。
手動計算とエクセル関数を使った場合。
分析基礎
・基本
結論は金額換算して分かりやすく。継続観察していくならKPIを設定する。
・サンプルの中で変数に属性を追加。
例)
来店率が下がっている顧客、上がっている顧客、特定の時期に上がる顧客等。
購入金額が高い顧客(Aランク)、低い顧客(Bランク)など。
これにより、顧客のニーズの仮説や、分析から排除の必要性等を検討する。
・次に他のサンプルと比較。
サンプル1(会員等)での特徴(標準偏差や中央値等)がサンプル2(非会員等)と比較してどう違うか。そうすることで、サンプル1はサンプル2と比べてはどのような特徴があるのか分かる。
・複数のサンプルでの比較
会員と商品の関係での特徴は、非会員と商品の関係と比較してどう違うか。
会員は特定商品のリピート率が高い等。
SQLで相関係数(傾き)
標準偏差や分散などは標準の関数であるが、相関係数はない。
集計用に傾きだけ欲しかったので、とりあえずSQLで求めた
テーブル名:t
結果:17.2482570475901
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
select t4.cor * ( t4.y_dev / t4.x_dev ) from ( select avg(t3.zz) / ( avg(t3.x_dev) * avg(t3.y_dev) ) as cor , avg(t3.x_dev) as x_dev , avg(t3.y_dev) as y_dev from ( select ( t2.xx * t2.yy ) as zz , t2.x_dev , t2.y_dev from ( select t.x_m , t.y_m , t.x_m - ( select avg(x_m) from t ) as xx , t.y_m - ( select avg(y_m) from t ) as yy , ( select stdevp(x_m) from t ) as x_dev , ( select stdevp(y_m) from t ) as y_dev from t ) as t2 ) as t3 ) as t4 |
傾きで利用したストアド
|
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 45 46 47 48 49 50 51 52 |
declare cur cursor for select distinct カード番号_s from tbl open cur declare @id bigint fetch next from cur into @id while @@fetch_status = 0 begin if 7 <> (select count(*) from tbl where カード番号_s = @id) goto brk select @id, t4.cor * ( t4.y_dev / t4.x_dev ) from ( select avg(t3.zz) / ( avg(t3.x_dev) * avg(t3.y_dev) ) as cor , avg(t3.x_dev) as x_dev , avg(t3.y_dev) as y_dev from ( select (t2.xx * t2.yy) as zz , t2.x_dev , t2.y_dev from ( select 集計期間月_m - ( select avg(集計期間月_m) from tbl where カード番号_s = @id ) as xx , 買上金額_m - ( select avg(買上金額_m) from tbl where カード番号_s = @id ) as yy , ( select stdevp(集計期間月_m) from tbl where カード番号_s = @id ) as x_dev , ( select stdevp(買上金額_m) from tbl where カード番号_s = @id ) as y_dev from tbl where カード番号_s = @id ) as t2 ) as t3 ) as t4 brk: fetch next from cur into @id end close cur deallocate cur |
SQl Server Management Studioでの結果をそのままエクセルに貼り付けたかったので、
以下のような書き方で解決した。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
declare @mydate nchar(10) set @mydate = '2017/1/1' select (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i <= 1), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i >= 2 and 買上回数_i <= 4), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i >= 5 and 買上回数_i <= 7), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i >= 8 and 買上回数_i <= 10), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i >= 11 and 買上回数_i <= 15), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i >= 16 and 買上回数_i <= 20), (select sum(買上金額_m) from tb4 where 集計期間月_d = @mydate and 買上回数_i >= 21) |
VBA SQL実験用②(SQL Server)
以前、Accessにテーブルを手軽作成するエクセルVBAがあったので、今回はSQL Server版。クエリの複数行対応と、シート名でテーブル作成へ少し修正している。
|
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
Sub auto_open() Application.CommandBars("cell").Reset With Application.CommandBars("cell").Controls.Add .OnAction = "t" .Caption = "テーブル作成・登録" End With With Application.CommandBars("cell").Controls.Add .OnAction = "tt" .Caption = "SQL実行" End With End Sub Sub auto_close() On Error Resume Next For i = 1 To 2 Application.CommandBars("cell").Controls("テーブル作成・登録").Delete Application.CommandBars("cell").Controls("SQL実行").Delete Next i End Sub Sub t() Set cn = CreateObject("adodb.connection") cn.Open "Provider=SQLOLEDB;Data Source=ESPRIMO\SQLEXPRESS;Initial Catalog=my_database;Integrated Security=SSPI;" tbl = ActiveSheet.Name 'テーブル削除 On Error Resume Next cn.Execute "drop table " & tbl 'テーブル作成 On Error GoTo 0 fld = "" For c = Selection(1).Column To Selection(Selection.Count).Column Select Case Right(ActiveSheet.Cells(Selection(1).Row, c).Value, 1) Case "s" tmp = "varchar(255)" Case "i" tmp = "bigint" Case "m" tmp = "money" Case "d" tmp = "date" End Select fld = fld & ActiveSheet.Cells(Selection(1).Row, c).Value & " " & tmp & "," Next c fld = Left(fld, Len(fld) - 1) q = "create table " & tbl & " (id integer identity(1,1) primary key," & fld & ")": Debug.Print q cn.Execute q 'データ登録 fld = "" For c = Selection(1).Column To Selection(Selection.Count).Column fld = fld & ActiveSheet.Cells(Selection(1).Row, c).Value & "," Next c fld = Left(fld, Len(fld) - 1) For r = (Selection(1).Row) + 1 To Selection(Selection.Count).Row For cc = Selection(1).Column To Selection(Selection.Count).Column rec = rec & "'" & ActiveSheet.Cells(r, cc).Value & "'" & "," Next cc rec = Left(rec, Len(rec) - 1) q = "insert into " & tbl & " (" & fld & ") values (" & rec & ")": Debug.Print q cn.Execute q rec = "" Next r If cn.State = 1 Then cn.Close Set cn = Nothing MsgBox "done" End Sub Sub tt() Set cn = CreateObject("adodb.connection") Set rn = CreateObject("adodb.recordset") cn.Open "Provider=SQLOLEDB;Data Source=ESPRIMO\SQLEXPRESS;Initial Catalog=my_database;Integrated Security=SSPI;" If Selection.Rows.Count = 1 Then rn.Open ActiveCell.Value, cn Else For r = 1 To Selection.Rows.Count q = q & " " & Selection(r) Next r rn.Open q, cn: Debug.Print q End If 'フィールド作成 i = 0 For c = Selection(1).Column To (Selection(1).Column + rn.Fields.Count) - 1 Cells(Selection(Selection.Count).Row + 1, c).Value = rn.Fields(i).Name i = i + 1 Next c 'データ読込 Cells(Selection(Selection.Count).Row + 2, Selection(1).Column).CopyFromRecordset rn If rn.State = 1 Then rn.Close Set rn = Nothing If cn.State = 1 Then cn.Close Set cn = Nothing End Sub |
AccessVBA クエリを呼び出す
|
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 |
Sub test() 'Accessにあるクエリを作成するプロシージャを呼ぶ 'クエリを作ってあるmdbなら不要 Set a = CreateObject("Access.Application") With a .OpenCurrentDatabase "xxx.mdb" .Visible = False .Application.Run "xxx" .Quit End With Set a = Nothing 'ここからはADO Set c = CreateObject("ADODB.Connection") Set r = CreateObject("ADODB.Recordset") c.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=xxx.mdb;" r.Open "test", c 'クエリで動的なテーブルを開く。 'ちゃんとSQL Serverまで読みにいっている。Accessの中にキャッシュなどしていないよう ActiveSheet.Cells(1, 1).CopyFromRecordset r End Sub |
C# Access(accdb) 比較
業者製作のAccessファイル+クライアントで、クライアントプログラム側で操作した結果が
Access内部でどう変更されるか調べようと思ったがAccessファイルが大きすぎた。
|
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; /* Microsoft Access データベース エンジン 2010 再頒布可能コンポーネント (AccessDatabaseEngine.exe) ファイルがaccdb、ACE.OLEDB.12.0を利用する場合、 PCが32bitならインストールしないとプロバイダが見つからない。*/ namespace データベース差分チェック { public partial class Form1 : Form { UserDataSet uds1 = null; UserDataSet uds2 = null; public Form1() { InitializeComponent(); comboBox1.Enabled = false; comboBox2.Enabled = false; comboBox1.SelectedIndexChanged += new EventHandler(ComboxChange1); comboBox2.SelectedIndexChanged += new EventHandler(ComboxChange2); } private void ComboxChange1(object sender, EventArgs e) { if (uds1 == null) return; dataGridView1.DataSource = uds1.AccessDataSet.Tables[comboBox1.Text]; } private void ComboxChange2(object sender, EventArgs e) { if (uds2 == null) return; dataGridView2.DataSource = uds2.AccessDataSet.Tables[comboBox2.Text]; } private void button1_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { if (listBox1.Items.Count <= 1) { listBox1.Items.Add(ofd.FileName); } else { listBox1.Items[0] = listBox1.Items[1]; listBox1.Items.RemoveAt(1); listBox1.Items.Add(ofd.FileName); } } } private void button2_Click(object sender, EventArgs e) { comboBox1.Items.Clear(); comboBox2.Items.Clear(); if (listBox1.Items.Count == 1) { this.uds1 = new UserDataSet(listBox1.Items[0].ToString()); for (int i = 0; i < uds1.AccessDataSet.Tables.Count; i++) { comboBox1.Items.Add(uds1.AccessDataSet.Tables[i].TableName); } comboBox1.Enabled = true; } if (listBox1.Items.Count == 2) { this.uds2 = new UserDataSet(listBox1.Items[1].ToString()); for (int i = 0; i < uds2.AccessDataSet.Tables.Count; i++) { comboBox2.Items.Add(uds2.AccessDataSet.Tables[i].TableName); } comboBox2.Enabled = true; } } } public class UserDataSet { public DataSet AccessDataSet = new DataSet(); public UserDataSet(string filePath) { using (System.Data.OleDb.OleDbConnection con = new System.Data.OleDb.OleDbConnection( @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";JET OLEDB:Database Password=xxx")) { try { con.Open(); //fillの場合不要だがGetSchemaで必要。 DataTable dt = con.GetSchema("Tables"); foreach (DataRow r in dt.Rows) { string tableName = r["TABLE_NAME"].ToString(); //System.Diagnostics.Debug.Print(r["TABLE_NAME"].ToString()); if (tableName.Substring(0, 4) != "MSys") { using (System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter()) { System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand("select * from " + tableName, con); da.SelectCommand = cmd; DataTable newTable = new DataTable(tableName); AccessDataSet.Tables.Add(newTable); da.Fill(AccessDataSet.Tables[tableName]); } } } } catch(Exception e) { MessageBox.Show(e.Message); return; } finally { con.Close(); } } } } } |
C# 設計メモ
順不同。思いつたら更新。
・クラスの単位
GUIのフォーム単位のクラスが基本(GUIがなければユースケース管理)で、その中で必要に応じてクラスに抜き出す。
1.変更の発生しそうな部分をクラスに抜き出す。
拡張ポイント(DI)
2.共通で使う部分をクラスに抜き出す。
アダプター(合成+委譲)で共通化
ストラテジー
3.他クラスから参照される部分をクラスに抜き出す。
4.テストしたい部分をクラスに抜き出す。
5.インスタンス生成をクラスに抜き出す。
生成処理を1箇所にまとめることで変更に対応しやすく。
DIが連続して上位レイヤーに引数が溢れてきたら。
(作ると使うを分ける)
6.プリミティブな値に型定義する場合。
値オブジェクト
・クラス、インターフェース、メソッド
参照と変更を分ける(CQS)。意味のある名前にする。スコープが大きいのに一文字変数名や、ハードコーディングしている数値など避ける。とりあえずメソッドは小さく。
・レイヤー
適切にクラス分けしていけば最終的に自然とレイヤーに当てはまる形になっているのでそれほど意識しない。
・依存関係のコントロール
クラス間の依存をインターフェースへの依存にすること。派生クラスの追加で対応する。拡張ポイントと呼ぶ場合もある。
|
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); // 下位レイヤーに依存すると下位レイヤーの変更に影響を受ける new App(""); // AppでSayHelloのインスタンス生成をしている new App(); // SayHelloのインスタンスをBuilderで生成し、App内で利用している // (生成と利用の分離) new App(new Builder()); // Builderの生成をAppの生成と同じレイヤー化 // AppはBuilderに依存(利用)していたが、 // App、BuilderともにIFactoryに依存することになる // (DI) } } class App { public App(string dummy) { new SayHello().Do(); } public App() { new Builder().CreateObj().Do(); } public App(IFactory f) { f.CreateObj().Do(); } } class Builder : IFactory { public SayHello CreateObj() { return new SayHello(); } } interface IFactory { SayHello CreateObj(); } class SayHello { public void Do() { MessageBox.Show("hello"); } } |
・DB系
DBの依存関係。FKがある方が依存している。依存している方が子。PKは重複できないけど、FKは重複できるので、FKある方が多。
複合主キーとなっている関係従属を取り除く正規化は当たり前に発生するので、正しいモデリングをすると必然的に複合主キーが現れる。サロゲートキーを入れる場合、制約はアプリ側で対応する。例えば仕入価格を、仕入先・商品・開始年月で識別するような場合。
参照整合性。実務では完全な制約が必要ではなく、緩い制約の方が都合がいいときもある。ただし、構造が壊れやすくはなるので注意。
SQL DB正規化
直ぐ忘れてしまう。
先ず、一方の値が決まると他方も決まるものを、関数従属性という。
第一正規化
一つのセルに複数のデータを持たない。
第二正規化
部分関数従属を取り除く。
部分関数従属とは、主キーの一部だけで一意に決まる列のこと。
主キーが複数あり、その内の一つだけで値が決まるものを別のテーブルにする。
第三正規化
推移的関数従属を取り除く。
推移的関数従属とは、テーブル内の段階的な関数従属のこと。
つまり、主キー以外と関数従属があること。
主キー以外の項目で、他の列の値を一意に決めるものを別テーブルにする。
例えば、(主)社員ID → 部署コード → 部署名
部署コードが決まれば部署名が決まる。当然主である社員IDと部署コードは関数従属の関係なので、
段階的な関数従属があるといえる。
部分関数従属、推移的関数従属を取り除くことの必要性。
あるテーブルの中で推移的関数従属が残っていると、間違った登録が可能。(会社コードと会社名)
また、主キーが不明の段階で登録できない。
キー| メンバー名 | 会社コード | 会社名
1 | 太郎 | 0000 | AAA
2 | 次郎 | 0001 | AAA
テーブルの関連
1対1、1対多、多対多があるが、通常1対多のみ使う。
多対多となる場合、関連実体というテーブルを作る。ただ、通常の業務要件では、
マスタとマスタを直接関連付けることはないので、普通に考えると多対多とはならない。
Ubuntu Java Tomcatインストール
インストール
sudo apt-get install defaut-jdk
java -version
今回は、1.8.0_121
sudo apt-get install tomcat7
sudo update-alternatives –list java
でJavaのパスを確認。
今回は、
/usr/lib/jvm/java-8-openjdk-i386/jre/bin/java
と表示される。
~/.profile
に以下を追記する。
JAVA_HOME=”/usr/lib/jvm/java-8-openjdk-i386/jre/bin/java”
PATH=”$JAVA_HOME/bin:$PATH”
CATALINA_HOME=”/usr/share/tomcat7″
profileの記述で違う方法として、
/etc/profile.d/java.sh
を作成し、
JAVA_HOME=”/usr/lib/jvm/java-8-openjdk-i386/jre/bin/java”
と追記し、
source ./java.sh
を実行する方法もある。今回はやらない。
ここで再起動。
echo $JAVA_HOME
で確認すると、
/usr/lib/jvm/java-8-openjdk-i386/jre/bin/java
と表示される。
ファイアーウォールの設定
sudo ufw allow 8080/tcp
ここまで来たら、
sudo /etc/init.d/tomcat7 restart
を実行。
http://192.168.102.15:8080/
にアクセス。
その他
設定ファイルの場所
sudo vim /etc/tomcat7/server.xml
Tomcatの状況確認
sudo /etc/init.d/tomcat7 status
もしeclipseでTomcatを操作する場合
http://www.eclipsetotale.com/tomcatPlugin.html#A3
から
tomcatPluginV331.zip
を保存し解凍して、
C:\eclipse\plugins
の中へ
C# Interpreter
|
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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
namespace ConsoleApplication2 { /* Interpreter 規則のあるフォーマットを解析し処理する。 */ public interface Operand { //処理対象を表す文字列を返す string GetOperandString(); } //処理対象クラス public class Ingredient : Operand { //処理対象を表す文字列 private string OperandString = ""; public Ingredient(string operandString) { this.OperandString = operandString; } //処理対象を表す文字列を返す。 public string GetOperandString() { return this.OperandString; } } //処理結果クラス public class Expression : Operand { private Operator operate = null; //処理内容を表すOperatorを引数にとる public Expression(Operator operate) { this.operate = operate; } //処理の結果得られるOperandの文字列表現を返す。 public string GetOperandString() { return operate.Execute().GetOperandString(); } } public interface Operator { Operand Execute(); } //処理の実行 public class Plus : Operator { private Operand operand1 = null; private Operand operand2 = null; public Plus(Operand operand1, Operand operand2) { this.operand1 = operand1; this.operand2 = operand2; } public Operand Execute() { return new Ingredient(this.operand1.GetOperandString() + " + " + this.operand2.GetOperandString() + ""); } } class Program { static void Main(string[] args) { Expression expression1 = new Expression(new Plus(new Ingredient("1"),new Ingredient("2"))); System.Console.WriteLine(expression1.GetOperandString()); Expression expression2 = new Expression(new Plus(expression1, new Ingredient("2"))); System.Console.WriteLine(expression2.GetOperandString()); System.Console.ReadKey(); } } } |