我有一张桌子,我会计算一个元素出现的频率。
为此,我可以使用Sequel::Dataset#group_and_count
。
但现在我想算一下这个结果。我怎么能这样做?
require 'sequel'
Sequel.extension :pretty_table
DB = Sequel.sqlite()
DB.create_table( :test ){
add_field :key, :type => :nvarchar, :size => 10
add_field :value, :type => :nvarchar, :size => 10
}
'a'.upto('f'){|a|
a.upto('x'){|b|
DB[:test].insert( :key => a, :value => b)
}
}
sel = DB[:test].group_and_count(:key)
puts Sequel::PrettyTable.string(sel)
这给了我:
+-----+---+
|count|key|
+-----+---+
| 24|a |
| 23|b |
| 22|c |
| 21|d |
| 20|e |
| 19|f |
+-----+---+
现在我想计算一下计数值的发生频率。
我的结果应该是:
+-----------+-----+
|count_value|count|
+-----------+-----+
| 24 | 1 |
| 23 | 1 |
| 22 | 1 |
| 21 | 1 |
| 20 | 1 |
| 19 | 1 |
+-----------+-----+
我可以通过以下方式获得此结果:
mycount = Hash.new(0)
DB[:test].group_and_count(:key).each{| res |
mycount[res[:count]] += 1
}
p mycount # {24=>1, 23=>1, 22=>1, 21=>1, 20=>1, 19=>1}
使用SQL(参见SQL Group by Count of Counts)我可以执行以下命令:
puts DB.fetch(<<-sql ).all
select count_value, count(*) as count from (
select count(*) as count_value from test group by key
)
group by count_value
sql
但是我正在寻找一种方法来使用Sequel命令(如果可能的话)。
group_and_count
不可链接:
#SQLite3::SQLException: no such column: count (Sequel::DatabaseError)
sel = DB[:test].group_and_count(:key).group_and_count(:count)
也无法重命名:count
sel = DB[:test].group_and_count(:key).select(:count.as(:count_value))
如果我定义了一个视图,我会得到一个DatabaseError:
DB.create_view(:count_testkey, DB[:test].group_and_count(:key))
sel = DB[:count_testkey].group_and_count(:count)
#SQLite3::SQLException: aggregate functions are not allowed in the GROUP BY clause (Sequel::DatabaseError)
puts Sequel::PrettyTable.string(sel)
答案 0 :(得分:0)
我找到了解决方案:
sel = DB[:test].select(:count_value, Sequel::SQL::Function.new(:count, Sequel::Dataset::WILDCARD).as(:count)).group_by(:count_value)
.from(
DB[:test].select(Sequel::SQL::Function.new(:count, Sequel::Dataset::WILDCARD).as(:count_value)
).group_by(:key)
)
puts sel.sql.downcase
puts Sequel::PrettyTable.string(sel)
这会导致(SQL命令'由我精心打印):
select `count_value`, count(*) as 'count' from (
select count(*) as 'count_value' from `test` group by `key`) as 't1'
group by `count_value`
+-----+-----------+
|count|count_value|
+-----+-----------+
| 1| 19|
| 1| 20|
| 1| 21|
| 1| 22|
| 1| 23|
| 1| 24|
+-----+-----------+
基于此解决方案,我定义了一种新方法Sequel::Dataset#group_and_countcount
。
这是一个完整的例子:
require 'sequel'
Sequel.extension :pretty_table
DB = Sequel.sqlite()
DB.create_table( :test ){
add_field :key, :type => :nvarchar, :size => 10
add_field :value, :type => :nvarchar, :size => 10
}
'a'.upto('f'){|a|
a.upto('x'){|b|
DB[:test].insert( :key => a, :value => b)
DB[:test].insert( :key => 'x', :value => b) if a == 'a' #force one double count
}
}
puts "Test DB[:test].group_and_count(:key)"
sel = DB[:test].group_and_count(:key)
puts Sequel::PrettyTable.string(sel)
module Sequel
class Dataset
def group_and_countcount(key)
self.unfiltered.select(:count_value, Sequel::SQL::Function.new(:count, Sequel::Dataset::WILDCARD).as(:count)).group_by(:count_value)
.from(
self.select(Sequel::SQL::Function.new(:count, Sequel::Dataset::WILDCARD).as(:count_value)
).group_by(key)
)
end #group_and_countcount(key)
end
end
puts "Test DB[:test].group_and_countcount(:key)"
sel = DB[:test].group_and_countcount(:key)
puts Sequel::PrettyTable.string(sel)
结果:
Test DB[:test].group_and_count(:key)
+-----+---+
|count|key|
+-----+---+
| 24|a |
| 23|b |
| 22|c |
| 21|d |
| 20|e |
| 19|f |
| 24|x |
+-----+---+
Test DB[:test].group_and_countcount(:key)
+-----+-----------+
|count|count_value|
+-----+-----------+
| 1| 19|
| 1| 20|
| 1| 21|
| 1| 22|
| 1| 23|
| 2| 24|
+-----+-----------+