Ruby aggregate function with model - ruby-on-rails

I have a product model in my ruby on rails application which has name,endorsement and expense attributes.
I need to write a query that list all records, but for every record I need to calculate endorsement-expense as income value. That seems to be ok. However, I need to sum all of the incomes consequtively as well.
For example my records are like these:
Name Endorsement Expense
X 100 25
Y 20 17
X 60 55
T 178 78
I need to list those values as:
Name Endorsement Expense Income Total Income
X 100 25 75 75
Y 20 17 3 78
X 60 55 5 83
T 178 78 100 183
How can I do that ?
Thanks.

rows = Product.select('name,endorsement,expense, (endorsement-expense) as income')
total_income = 0
rows.each do |row|
total_income += row.income
puts "#{row.name}, #{row.endorsement}, #{row.expense}, #{row.income}, #{total_income}"
end

You can also do it with a total income for each product:
products = Product.select("(endorsement - expense) AS 'income', name, endorsement, created_at, null as total")
products.each do |p|
p.total = Product.select("sum(endorsement) - sum(expense) AS 'total'").where(name: p.name).where("created_at <= ?", p.created_at).group('name').last.total
end

You can apply inject function to accumulate total income.
It will look something like this:
products.inject{|sum, product| sum += (product.endorsement - product.expense }

Related

Ruby on rails calculating total sum

id
tithe
offertory
pledge
Total
1
120
230
280
???
I have a table like this and I want the total = tithe + offertory + pledge.
how do I write a query for this?
With the use of sum:
Record.where(id: 1).sum('tithe + offertory + pledge')

Neo4j compare sums from different queries and display result

Is there a way that i compare results from different queries? Could the following queries be written in a single query together with the return for the wanted result?
Query1: Returns countries and SUM from all points given by countries that are not part of their region.
MATCH (c:Country)
with c
MATCH (c)-[vFrom:vote_from]->(vP:vote_points)-[vFor:vote_for]->(c2:Country)
with c,c2,vP
where not c.region=c2.region
return c2.name,sum(toInteger(vP.points))
Example return from Query1:
"Monaco" 11
"Montenegro" 34
"France" 359
"Cyprus" 600
"Romania" 837
Query2: Returns countries and SUM from all points given by countries that are part of their region.
MATCH (c:Country)
with c
MATCH (c)-[vFrom:vote_from]->(vP:vote_points)-[vFor:vote_for]->(c2:Country)
with c,c2,vP
where c.region=c2.region
return c2.name,c.name,sum(toInteger(vP.points))
Example return from Query2:
"Monaco" 35
"Montenegro" 66
"France" 157
"Cyprus" 102
"Romania" 255
Wanted result:
"Monaco" 35
"Montenegro" 66
Assuming that you are looking for cases where in-region point totals exceed out-of-region totals, this query may work for you:
MATCH (c:Country)-[:vote_from]->(vP:vote_points)-[:vote_for]->(c2:Country)
WITH c2,
REDUCE(s={in: 0, out: 0}, x IN COLLECT({reg: c.region, pts: toInteger(vP.points)}) |
CASE WHEN x.reg=c2.region
THEN {in: s.in + x.pts, out: s.out}
ELSE {in: s.in, out: s.out + x.pts}
END) AS res
WHERE res.in > res.out
RETURN c2.name AS name, res.in AS points

formatting strings in lua in a pattern

I want to make a script that takes any number, counts up to them and returns them in a format.
so like this
for i = 1,9 do
print(i)
end
will return
1
2
3
4
5
6
7
8
9
however I want it to print like this
1 2 3
4 5 6
7 8 9
and I want it to work even with things more than 9 so things like 20 would be like this
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
16 17 18
19 20
I'm sure it can be done using the string library in lua but I am not sure how to use that library.
Any help?
function f(n,per_line)
per_line = per_line or 3
for i = 1,n do
io.write(i,'\t')
if i % per_line == 0 then io.write('\n') end
end
end
f(9)
f(20)
The for loop takes an optional third step:
for i = 1, 9, 3 do
print(string.format("%d %d %d", i, i + 1, i + 2))
end
I can think of 2 ways to do this:
local NUMBER = 20
local str = {}
for i=1,NUMBER-3,3 do
table.insert(str,i.." "..i+1 .." "..i+2)
end
local left = {}
for i=NUMBER-NUMBER%3+1,NUMBER do
table.insert(left,i)
end
str = table.concat(str,"\n").."\n"..table.concat(left," ")
And another one using gsub:
local NUMBER = 20
local str = {}
for i=1,NUMBER do
str[i] = i
end
-- Makes "1 2 3 4 ..."
str = table.concat(str," ")
-- Divides it per 3 numbers
-- "%d+ %d+ %d+" matches 3 numbers divided by spaces
-- (You can replace the spaces (including in concat) with "\t")
-- The (...) capture allows us to get those numbers as %1
-- The "%s?" at the end is to remove any trailing whitespace
-- (Else each line would be "N N N " instead of "N N N")
-- (Using the '?' as the last triplet might not have a space)
-- ^ e.g. NUMBER = 6 would make it end with "4 5 6"
-- The "%1\n" just gets us our numbers back and adds a newline
str = str:gsub("(%d+ %d+ %d+)%s?","%1\n")
print(str)
I've benchmarked both code snippets. The upper one is a tiny bit faster, although the difference is almost nothing:
Benchmarked using 10000 interations
NUMBER 20 20 20 100 100
Upper 256 ms 276 ms 260 ms 1129 ms 1114 ms
Lower 284 ms 280 ms 282 ms 1266 ms 1228 ms
Use a temporary table to contain the values until you print them:
local temp = {}
local cols = 3
for i = 1,9 do
if #temp == cols then
print(table.unpack(temp))
temp = {}
end
temp[#temp + 1] = i
end
--Last minute check for leftovers
if #temp > 0 then
print(table.unpack(temp))
end
temp = nil

How to get next records `bending` by order?

Let say I have a model Product with columns id and sort_number.
id | sort_number (random)
1 | 325
2 | 161
3 | 58
...
147 | 500 # the biggest sort_number number is equal to the Product.count result
...
500 | 5
I want a next(n = 20) and previous(n = 20) methods for the Product instances. IE if I:
product = Product.find(43)
product.sort_number # => 490
product.next(20) # should return products with sort_number equal to (491..500) + (1..10)
How can I implement this functionality? How can I get the next record with sort_number started at 1, if there are no more records next?
OK, I will put this as an answer.
def next id, count
product = Product.find(id)
products = Product.where(
'sort_number > ? AND sort_number <= ?',
product.sort_number, product.sort_number + count
) # this will return 20 requested, unless sort_number is near 500
products |= Product.where(
'sort_number > 1 AND sort_number <= ?',
count - product.count
) if products.count < count
products
end

Extracting sampled Time Points

I have a matlab Curve from which i would like to plot and find Concentration values at 17 different time samples
Following is the curve from which i would like to extract Concentration values at 17 different time points
following are the time points in minutes
t = 0,0.25,0.50,1,1.5,2,3,4,9,14,19,24,29,34,39,44,49. minutes samples
Following is the Function which i have written to plot the above graph
function c_t = output_function_constrainedK2(t, a1, a2, a3,b1,b2,b3,td, tmax,k1,k2,k3)
K_1 = (k1*k2)/(k2+k3);
K_2 = (k1*k3)/(k2+k3);
DV_free= k1/(k2+k3);
c_t = zeros(size(t));
ind = (t > td) & (t < tmax);
c_t(ind)= conv(((t(ind) - td) ./ (tmax - td) * (a1 + a2 + a3)),(K_1*exp(-(k2+k3)*t(ind)+K_2)),'same');
ind = (t >= tmax);
c_t(ind)= conv((a1 * exp(-b1 * (t(ind) - tmax))+ a2 * exp(-b2 * (t(ind) - tmax))) + a3 * exp(-b3 * (t(ind) - tmax)),(K_1*exp(-(k2+k3)*t(ind)+K_2)),'same');
plot(t,c_t);
axis([0 50 0 1400]);
xlabel('Time[mins]');
ylabel('concentration [Mbq]');
title('Model :Constrained K2');
end
If possible, Kindly please suggest me some idea how i could possibly alter the above function so that i can come up with concentration values at 17 different time points stated above
Following are the input values that i have used to come up with the curve
output_function_constrainedK2(0:0.1:50,2501,18500,65000,0.5,0.7,0.3,3,8,0.014,0.051,0.07)
This will give you concentration values at the time points you wanted. You will have to put this inside the output_function_constrainedK2 function so that you can access the variables t and c_t.
T=[0 0.25 0.50 1 1.5 2 3 4 9 14 19 24 29 34 39 44 49];
concentration=interp1(t,c_t,T)

Resources