2013-10-06 26 views
1

我從外部數據庫獲取數據,並將其提供給我的瀟灑小部件。如何將MySQL語句翻譯爲數值?

當數值數據返回到窗口小部件,它看起來像:

mysql::result:0x21A25 

我需要這個數據是一個十進制數。下面是用於取數據,並將其饋送到一個插件的代碼:

require 'mysql2' 

SCHEDULER.every '1m', :first_in => 0 do |job| 

    # Mysql connection 

    db = Mysql2::Client.new(:host => "some ip", :username => "user", :password => "password", :port => 3306, :database => "database_name") 

    # Mysql query 

    sql = "SELECT COUNT(*) FROM out_sms WHERE type = 'STANDARD_SMS' " 
    # Execute the query 
    results = db.query(sql) 


    # Update the Man Hours Saved E widget 

    send_event('manHoursE', { current: results }) 

end 
+0

它說mysql :: results:0x25AD3未定義方法獲取行。這是正確的語法? –

+0

對不起,這是錯誤或過時的信息。結果對象是一個Enumerable。你可以做一些像'results.each {| r | ...}來查看它包含的內容。 –

+0

建議爲'COUNT()'使用別名,以便更容易檢索。 'SELECT COUNT(*)AS num FROM ...'由於這個查詢只能返回一行,而'results'是可枚舉的,所以你可以抓取'results.first',它應該是一個包含一個元素的散列。 –

回答

1

Mysql2::Client#query方法將返回一個Mysql2::Result對象,它是一個Ruby Enumerable。這意味着你可以通過很多不同的方法迭代它,就像你使用陣列或散列(例如results.each {})或use Enumerable methods(如.first.last)。

您的查詢,沒有GROUP BY只能返回一行。所以撥打.first會給你那一行。

# Use an alias for the count, total here 
sql = "SELECT COUNT(*) AS total FROM out_sms WHERE type = 'STANDARD_SMS' " 
# Execute the query 
results = db.query(sql) 

# Then retrieve the row using a method like .first 
your_row = results.first 

# Look at the hash it contains: 
puts your_row 

# The value you want should be a hash key 
puts your_row['total'] 

然後,您可以在更新方法中使用your_row['total']

當然,你可以簡化它,只需使用results.first['total']。不要忘記把它包裝在一個合適的begin ... rescue ... end來處理錯誤。

+0

哇,你是個魔術師。謝謝一堆先生! –

+0

@AdmirHuric樂於幫忙,歡迎來到Stack Overflow。 –

0

Mysql2 #query方法返回類型爲'Mysql2 :: Result'的對象。

你可以看到這裏的類:

results.class => Mysql2 ::結果

你可以在這裏數組:

results.to_a => [{「COUNT(*)」=> 26797}]

而且,如果你只是想整數值:

results.to_a [0] [ 「COUNT(*)」] => 26797

重命名您的計數('COUNT(* )作爲「sms_count」')將導致更可讀的結果。

0

我強烈建議查看Ruby的ORM之一,例如Sequel,DataMapperActive Record

通過使用自己的DSL抽象查詢,您可以使您的生活變得更加簡單,讓您專注於邏輯,並將字段的內容作爲Ruby中的本機對象返回。沒有更多像你一樣的問題。

這些工具生成的SQL等於您手動生成的;你必須努力工作才能讓他們做錯事,很少有人能夠改進他們所產生的東西。另外,只需更改連接DSN,您就可以切換到完全不同的數據庫管理器,並且他們會感受到架構差異,併爲新環境生成優化的SQL。嘗試直接與MySQL,PostgreSQL,Oracle或SQLite驅動程序交流。

這裏是你的代碼可能是你的什麼樣的使用續集和SQLite的例子:

Item count: 3 
{:id=>1, :name=>"abc", :number=>1, :price=>48.3673258126733} 
{:id=>2, :name=>"def", :number=>3, :price=>41.87676958348104} 
{:id=>3, :name=>"ghi", :number=>7, :price=>62.54605297923891} 

在循環提取行:

items.each do |i| 
    puts i 
end 

require 'sequel' 

DB = Sequel.sqlite # memory database 

DB.create_table :items do 
    primary_key :id 
    String :name 
    Integer :number 
    Float :price 
end 

items = DB[:items] # Create a dataset 

# Populate the table 
items.insert(:name => 'abc', :number => 1, :price => rand * 100) 
items.insert(:name => 'def', :number => 3, :price => rand * 100) 
items.insert(:name => 'ghi', :number => 7, :price => rand * 100) 

# Print out the number of records 
puts "Item count: #{ items.count }" 

# Print out the values: 
items.each do |i| 
    puts i 
end 

它返回這個運行後

每次通過循環i是一個散列,使它很容易提取單個字段。再次運行代碼:

>> item = items.first 
{ 
     :id => 1, 
     :name => "abc", 
    :number => 1, 
    :price => 70.81654554223003 
} 
>> item.class 
Hash < Object 

請注意,整數和浮點值是我們所期望的。 (「價格」字段的值因隨機而不同)。

對於Rails,您會遇到活動記錄,因爲它是ORM。在Rails之外使用Active Record是可行的,但它面向該框架。我們廣泛使用Sequel在我們的團隊中進行數據庫交互。我的代碼合作伙伴最近通過更改連接字符串,運行我們設置的遷移以及啓動數據重新加載,在大約一個小時內完成了從基於MySQL的數據庫到PostgreSQL的完整轉換。他對於它的容易程度非常滿意,特別是因爲他不必編寫任何SQL。

續集帶有一個基於IRB的命令行版本。您可以交互式查詢數據庫,修改數據庫,查看並查看其內容。這也是一個很好的方式來看看會產生什麼:

Your database is stored in DB... 
Welcome to SEQUEL. You are using ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]. Have fun ;) 
>> require 'logger' 
true 
>> DB.loggers << Logger.new(STDOUT) 
[ 
    [0] #<Logger:0x007f7fe41dd880 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x007f7fe41dd858 @datetime_format=nil>, @formatter=nil, @logdev=#<Logger::LogDevice:0x007f7fe41dd808 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<IO:<STDOUT>>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x007f7fe41dd7e0 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x007f7fe41dd790>>>> 
] 
>> DB.create_table :items do 
>  primary_key :id 
|  String :name 
|  Integer :number 
|  Float :price 
| end 
I, [2013-10-06T09:51:55.752052 #6721] INFO -- : CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, name varchar(255), number integer, price double precision) 
nil 
>> items = DB[:items] 
#<Sequel::Mock::Dataset: "SELECT * FROM items"> 
>> items.insert(:name => 'abc', :number => 1, :price => rand * 100) 
I, [2013-10-06T09:52:15.421974 #6721] INFO -- : INSERT INTO items (name, number, price) VALUES ('abc', 1, 22.32640955200822) 
nil 
>> items.insert(:name => 'def', :number => 3, :price => rand * 100) 
I, [2013-10-06T09:52:15.432649 #6721] INFO -- : INSERT INTO items (name, number, price) VALUES ('def', 3, 43.182983199793824) 
nil 
>> items.insert(:name => 'ghi', :number => 7, :price => rand * 100) 
I, [2013-10-06T09:52:15.441312 #6721] INFO -- : INSERT INTO items (name, number, price) VALUES ('ghi', 7, 67.81054007143193) 
nil 
>> items.count 
I, [2013-10-06T09:52:23.683121 #6721] INFO -- : SELECT count(*) AS count FROM items LIMIT 1 
0