CSV ファイルをデータベースにロード(天候データ) Rubyで処理
データベースのCLIでCSVからのロードコマンドは提供されているので、そのままなら、開発は不要。
データ加工などある場合に有効
require 'csv' require "date" require 'sqlite3' # sqlite3読み込み begin db = SQLite3::Database.new 'health.db' rescue SQLite3::SQLException => e puts "open database return: " puts "#{e}\n" end table_name = "weather" puts "$0:#{$0}" ARGV.each_with_index do |arg, i| puts "ARGV[#{i}]:#{arg}" csvfile = ARGV[i] csv_data = CSV.read(csvfile) sum = 0.0 cnt = 0 max = -999.0 min = 999.999 fromdate = nil todate = nil csv_data.each do |data| if fromdate == nil fromdate = data[0] end todate = data[0] intro_msg = "#{data[0]}の#{data[1]}平均気温(℃)、#{data[10]}天気概況(昼:06時~18時)です。\n" if data[1] == nil puts 'no data ' + intro_msg next else sum = sum + data[1].to_f cnt = cnt + 1 if max < data[1].to_f max = data[1].to_f end if min > data[1].to_f min = data[1].to_f end # 各行 # 0 wdate text, /* 年月日 */ # 1 avgtemp real, /* 平均気温(℃) */ # 2 avgtempqi integer, /* 平均気温(℃)品質情報 */ # 3 avgtemphn integer, /* 平均気温(℃)均質番号 */ # 4 maxtemp real, /* 最高気温(℃) */ # 5 maxtempqi integer, /* 最高気温(℃)品質情報 */ # 6 maxtemphn integer, /* 最高気温(℃)均質番号 */ # 7 mintemp real, /* 最低気温(℃) */ # 8 mintempqi integer, /* 最低気温(℃)品質情報 */ # 9 mintemphn integer, /* 最低気温(℃)均質番号 */ # 10 Weatherreport text, /* 天気概況(昼:06時~18時) */ # 11 weatherqi integer, /* 天気概況(昼:06時~18時)品質情報 */ # 12 Weatherhn integer /* 天気概況(昼:06時~18時)均質番号 */ sql = "INSERT INTO " + table_name + " VALUES (" num_lines = 0 j = 0 data.each do |field| cell = field.to_s # 「,,,」のような行では、フィールド値が nil になる。そのときは NULL if ( field.nil? ) sql = sql + "NULL" elsif ( field.empty? ) # 元の CSV ファイルで,「空」になっているようなセル sql = sql + "NULL" elsif ( j == 0 || j == 10 ) # Y/M/D -> YY/MM/DD if ( j == 0 ) d = Date.parse(cell) cell = d.strftime("%Y/%m/%d") end # 文字列属性のときは「'」で囲む. gsub を使い、文字列中の全ての「'」は「''」に置き換える(これは SQL の流儀) sql = sql + "'" + cell.gsub("'","''") + "'" elsif # 数値("INTEGER" または "REAL")のときは,文字列の先頭と末尾の空白文字を取り除く sql = sql + cell.strip end if ( j < (data.size - 1) ) # 最後のフィールドでないときは「,」で継続 sql = sql + ", " end j += 1 end # 最後は「);」で終わる sql = sql + ");" num_lines += 1 # 1000 行ごとにコミット if num_lines == 1000 db.execute("COMMIT;") puts "commit return\n" db.execute("BEGIN TRANSACTION;") puts "BEGIN TRANSACTION return\n" num_lines = 0 end begin db.execute(sql) rescue SQLite3::SQLException => e puts "#{sql} database return:}" puts "#{e}\n" end puts "record:#{cnt.to_s} #{sql} return\n}" end end db.close puts "database close return\n}" puts 'start:' + fromdate + ' to:' + todate + "\n" total_msg = "合計件数:#{cnt} 平均気温(℃):#{(sum/cnt).round(3)} MAX平均気温(℃):#{max} MIN平均気温(℃):#{min}\n" puts total_msg end