2016-02-24 47 views
0

使用Ruby自動化遠程數據庫中的MySQL查詢,我希望根據下面找到的month查詢的值拆分行。使用Ruby分割MySQL查詢的行並寫入CSV文件

這是針對所有基於開始日期的客戶在2014年6月份生成的每週(週三到下列Tueday)報告。雖然報告中沒有其他內容會發生變化,但是行的重複取決於該起始日期(在下面的case聲明中進行了說明)。

請注意這裏使用的mysql2watircsv寶石。

簡化代碼:

#!/usr/local/bin/ruby 
require "mysql2" 
require "watir" 
require "csv" 

puts "Initializing Report" 

Mysql2::Client.default_query_options.merge!(:as => :array) 

mysql = Mysql2::Client.new(:host => "1.2.3.4", :username => "user", :pass => "password", :database => "db") 

puts "Successfully accessed db" 

month = mysql.query("SELECT DATE_FORMAT(db.table.start, '%m') FROM db.table WHERE db.start.group = 1;") 

day = mysql.query("SELECT DATE_FORMAT(db.table.start, '%d') FROM db.table WHERE db.start.group = 1;") 

report = mysql.query("SELECT db.table.client, SELECT DATE_FORMAT(db.table.start, '%m/%d/%Y'), SELECT DATE_FORMAT(db.table.end, '%m/%d/%Y') FROM db.table WHERE db.start.group = 1;") 

case month 
when 5 
    # code splitting one row into four 
when 6 
    if day <= 4 
    # code splitting one row into four using weekOf 
    elsif day >= 11 and day <= 17 
    # code splitting one row into three using weekOf 
    elsif day >= 18 and day <= 24 
    # code splitting one row into two using weekOf 
    else 
    # no splitting; only one row using weekOf 
    end 
end 

CSV.open("Report.csv", "wb") do |csv| 
    csv << ["Week of", "Client", "Start Date", "End Date"] 
    weekOf.zip(report).each {|row| csv << row.flatten} 
end 

puts "Results can be found in Report.csv" 

電流輸出(如果我註釋掉case聲明,去掉"Week of",在CSV頭和只寫report查詢到CSV):

Client, Start Date, End Date 
companyrecordlabel, 05/20/2014, 07/09/2015 
beeUrself, 05/27/2014, 02/01/2016 
overflowStack, 06/04/2014, 12/11/2015 
chapoChaps, 06/11/2014, 01/16/2016 
Meds4U, 06/18/2014, NULL 
    . 
    . 
    . 

我希望以下輸出:

Week of, Client, Start Date, End Date 
06/04/2014, companyrecordlabel, 05/20/2014, 07/09/2015 
06/11/2014, companyrecordlabel, 05/20/2014, 07/09/2015 
06/18/2014, companyrecordlabel, 05/20/2014, 07/09/2015 
06/25/2014, companyrecordlabel, 05/20/2014, 07/09/2015 
06/04/2014, beeUrself, 05/27/2014, 02/01/2016 
06/11/2014, beeUrself, 05/27/2014, 02/01/2016 
06/18/2014, beeUrself, 05/27/2014, 02/01/2016 
06/25/2014, beeUrself, 05/27/2014, 02/01/2016 
06/04/2014, overflowStack, 06/04/2014, 12/11/2015 
06/11/2014, overflowStack, 06/04/2014, 12/11/2015 
06/18/2014, overflowStack, 06/04/2014, 12/11/2015 
06/25/2014, overflowStack, 06/04/2014, 12/11/2015 
06/11/2014, chapoChaps, 06/11/2014, 01/16/2016 
06/18/2014, chapoChaps, 06/11/2014, 01/16/2016 
06/25/2014, chapoChaps, 06/11/2014, 01/16/2016 
06/18/2014, Meds4U, 06/18/2014, NULL 
06/25/2014, Meds4U, 06/18/2014, NULL 
    . 
    . 
    . 

爲了清楚起見:"Client"companyrecordlabel有四行,因爲它的"Start Date"在五月份,而"Client"Meds4U只分成兩行,因爲它的"Start Date"是在六月十八號。

回答

0

我構建了以下答案FULL代碼基於以下幾個假設:

  • 沒有DATE_FORMAT(db.table.end, '%m') = 6
  • 你希望上市是在他們被發現在訂單中所有的 公司(即 db.table.id
  • 查詢時間對您而言並不是一個巨大的問題
  • 您想要但不能忘記包含一個arra y named weekOf

您在查詢中似乎也有太多次SELECT這個詞。即使對於小如您所提供的樣品,你可能要分開,並避免將它全部在一行的查詢:

month = mysql.query("SELECT DATE_FORMAT(db.table.start, '%m') 
    FROM db.table 
    WHERE db.start.group = 1;") 

代替:

month = mysql.query("SELECT DATE_FORMAT(db.table.start, '%m') FROM db.table WHERE db.start.group = 1;")

而現在爲代碼本身:

#!/usr/local/bin/ruby 
require "mysql2" 
require "watir" 
require "csv" 

puts "Initializing Report" 

Mysql2::Client.default_query_options.merge!(:as => :array) 

mysql = Mysql2::Client.new(:host => "1.2.3.4", :username => "user", :pass => "password", :database => "db") 

puts "Successfully accessed db" 

date = mysql.query("SELECT DATE_FORMAT(db.table.start, '%m'), 
    DATE_FORMAT(db.table.start, '%d') 
    FROM db.table 
    WHERE db.start.group = 1;") 

report = mysql.query("SELECT c, s, e FROM (SELECT * FROM (SELECT db.table.id 
    db.table.client AS c, 
    DATE_FORMAT(db.table.start, '%m/%d/%Y') AS s, 
    DATE_FORMAT(db.table.end, '%m/%d/%Y') AS e 
    FROM db.table 
    WHERE db.start.group = 1 
    UNION ALL 
    SELECT db.table.id 
    db.table.client AS c, 
    DATE_FORMAT(db.table.start, '%m/%d/%Y') AS s, 
    DATE_FORMAT(db.table.end, '%m/%d/%Y') AS e 
    FROM db.table 
    WHERE db.start.group = 1 
    HAVING ((DATE_FORMAT(db.table.start, '%m') = 5) OR (DATE_FORMAT(db.table.start, '%d') <= 4)) 
    UNION ALL 
    SELECT db.table.id 
    db.table.client AS c, 
    DATE_FORMAT(db.table.start, '%m/%d/%Y') AS s, 
    DATE_FORMAT(db.table.end, '%m/%d/%Y') AS e 
    FROM db.table 
    WHERE db.start.group = 1 
    HAVING ((DATE_FORMAT(db.table.start, '%m') = 5) OR (DATE_FORMAT(db.table.start, '%d') <= 11)) 
    UNION ALL 
    SELECT db.table.id 
    db.table.client AS c, 
    DATE_FORMAT(db.table.start, '%m/%d/%Y') AS s, 
    DATE_FORMAT(db.table.end, '%m/%d/%Y') AS e 
    FROM db.table 
    WHERE db.start.group = 1 
    HAVING ((DATE_FORMAT(db.table.start, '%m') = 5) OR (DATE_FORMAT(db.table.start, '%d') <= 18))) AS alias 
    ORDER BY db.table.id) AS alias2;") 

weekOf = [] 

date.each do |mon, day| 
    if mon === 5 
    weekOf << "06/04/2014" 
    weekOf << "06/11/2014" 
    weekOf << "06/18/2014" 
    weekOf << "06/25/2014" 
    elsif mon === 6 
    if (day.to_i <= 4) 
     weekOf << "06/04/2014" 
     weekOf << "06/11/2014" 
     weekOf << "06/18/2014" 
     weekOf << "06/25/2014" 
    elsif ((day.to_i >= 11) && (day.to_i <= 17)) 
     weekOf << "06/11/2014" 
     weekOf << "06/18/2014" 
     weekOf << "06/25/2014" 
    elsif ((day.to_i >= 18) && (day.to_i <= 24)) 
     weekOf << "06/18/2014" 
     weekOf << "06/25/2014" 
    else 
     weekOf << "06/25/2014" 
    end 
    else 
    puts "Error: #{mon} is before May" 
    end 
end 

CSV.open("Report.csv", "wb") do |csv| 
    csv << ["Week of", "Client", "Start Date", "End Date"] 
    weekOf.zip(report).each {|row| csv << row.flatten} 
end 

puts "Results can be found in Report.csv" 

的解釋:

我假定查詢時間對於您看到您的示例查詢很小並且不包含JOIN而言不是一個大問題。如果你發現你的查詢變得大於十個左右INNER JOIN(比方說,每個表有成千上萬的條目),那麼這可能不再是你的最佳解決方案。

此解決方案有兩個零件。

第一個是使用UNION ALL重複數據庫本身的行。這意味着重複整個查詢並添加下面的標準來指定何時發生這種重複。 。

這也正是HAVING條款進來當使用UNION ALLHAVING必須以這種方式,而不是WHERE使用;因爲後者會導致MySQL的錯誤。

另請注意,作爲子查詢結果創建的每個MySQL表必須具有別名:aliasalias2。爲了ORDER BY db.table.id(關閉我的一個假設),我沒有使用一個,而是使用兩個嵌套查詢,然後只選擇我們需要的列作爲下一部分。

最後,我組合了兩個單獨的monthday,而是將它們變成了一個date:它將在迭代時返回一個二維數組。

第二個:我創建了weekOf數組,你可能打算但忘了包括。

然後我重複了date以便將右邊的"06/#{day}/2014"推入weekOf陣列。

就是這樣!我希望這有幫助。