I have a problem with Informix SQL syntax.
This is my SQL syntax
sql = "SELECT MONTH(startdatetime) MONTH, COUNT(sessionid) TotalCallsOffered, "+
" CASE" +
" WHEN MONTH(startdatetime) = 5" +
" THEN 'SUSUKUDA' " +
" END " +
"FROM agentconnectiondetail a WHERE MONTH(startdatetime) = 5 " +
"GROUP BY 1 ORDER BY 1 ASC";
and the output is
ERROR [HY000] [Informix][Informix ODBC Driver][Informix] The column ((expression))
must be in the GROUP BY list.
What must I do?
Informix follows the strict SQL standard and requires all non-aggregate values in the select list to be listed in the GROUP BY clause. Thus, the SQL must look like:
SELECT MONTH(startdatetime) AS Month, COUNT(sessionid) AS TotalCallsOffered,
CASE
WHEN MONTH(startdatetime) = 5
THEN 'SUSUKUDA'
END AS Susukuda
FROM agentconnectiondetail
WHERE MONTH(startdatetime) = 5
GROUP BY Month, Susukuda
ORDER BY Month ASC
I've chosen to name all three columns with AS and to GROUP BY those names (and ORDER BY them too).
My problem solved with this
SELECT MONTH(startdatetime) AS Month, COUNT(sessionid) AS TotalCallsOffered,
CASE
WHEN MONTH(startdatetime) = 5
THEN 'SUSUKUDA'
END AS Susukuda
FROM agentconnectiondetail
WHERE MONTH(startdatetime) = 5
GROUP BY 1, 3
ORDER BY 1
Related
I'm going to use the group by clause...max().
I'm using Informix version 10.
This is example table: table_a
col_a col_b col_c
1 20181010 3
1 20181030 4
I want to retrieve data with a recent date.
I want result :
col_a col_b col_c
1 20181030 4
When I use this query
#query 1: select col_a, max(col_b), col_c from table_a group by col_a
#result : The column (col_c) must be in the GROUP BY list.
#query 2: select col_a, max(col_b), col_c from table_a group by col_a, col_c
#result :
col_a col_b col_c
1 20181010 3
1 20181030 4
I think can I use MS SQL of row_num(partition by col_b)? but
Informix version 10 can't use row_num...
So, I use a join query
select a.col_a,a.col_b,a.col_c from table_a a
inner join (select col_a, max(col_b) as col_b from table_a group by col_a) b
on a.col_a = b.col_a and a.col_b = b.col_b
I got the results I wanted.
Is there a way to use join?
I am learning ActiveRecord. Can I build this query?
#sales_by_product = ActiveRecord::Base.connection.execute("SELECT
it.name,
it.id,
it.seller_id,
pur.volume,
pur.sales
FROM items it
INNER JOIN (SELECT
item_id,
COUNT(*) AS volume,
SUM(price) AS sales,
workflow_state AS state
FROM purchases
WHERE workflow_state = 'payment_successful'
GROUP BY item_id,
workflow_state) pur
ON pur.item_id = it.id
WHERE it.seller_id = '" + current_user.id.to_s + "'")
I would like to use the AR api as much as possible but I have not yet gotten the above to work using just AR.
Thanks!
I don't think it is a good idea to use AR for this query. It seems fun at first, but becomes annoying. And, it will be difficult to change later.
You can create your own query builder:
def query_for current_user
<<-SQL
SELECT
it.name,
it.id,
it.seller_id,
pur.volume,
pur.sales
FROM items it
INNER JOIN (SELECT
item_id,
COUNT(*) AS volume,
SUM(price) AS sales,
workflow_state AS state
FROM purchases
WHERE workflow_state = 'payment_successful'
GROUP BY item_id,
workflow_state) pur
ON pur.item_id = it.id
WHERE it.seller_id = '" + current_user.id.to_s + "'")
SQL
end
#sales_by_product = ActiveRecord::Base.connection.execute( query_for( current_user ))
i would like write this query in Rails/Active Record
SELECT * FROM messages WHERE (realtor_id,created_at) IN ( SELECT realtor_id, MAX(created_at),message FROM messages WHERE `messages`.`user_id` = 8 GROUP BY realtor_id );
I tried some syntaxes but it doesnt work...
I think, the solution is near :
#discussions = Message.where(realtor_id: created_at: [Message.where(:user_id => current_user.id).select("realtor_id, MAX(created_at) as created_at").group("realtor_id").order("created_at ASC")])
Someone can help me ?
Thanks for advance,
F.
You can create sql query and pass in
query = "SELECT * FROM messages WHERE (realtor_id,created_at) IN ( SELECT realtor_id, MAX(created_at),message FROM messages WHERE `messages`.`user_id` = 8 GROUP BY realtor_id )"
#discussions = ActiveRecord::Base.connection.execute(query)
I have 4 databases in my rails program, Products, Offerings, OfferingProducts, and Orders
Sample Offering: Medium Kit
Medium Kit Contains 2 Products (This is set up in the OfferingProduct db)
1 Small
2 Medium
customer Orders 2 medium kits
this program should account for 2 Small and 4 Medium from this order and many orders similar
I'm trying to set up an inventory system to track how many of each product are sold every week so that I can reorder products. To calculate this I have:
def get_trend
product = Product.first
customer_orders =[]
product.offerings.each do |o|
customer_orders = customer_orders + o.orders
end
o=customer_orders.group_by { |t| t.date.beginning_of_week }
y = []
op=self.offering_products;
o.sort.each do |week, orders|
y << orders.map { |o| o.quantity*op.find_by_offering_id(o.offering).quantity }.sum
end
return y
end
This seems to work, but it takes about 20 seconds to calculate. Is there any way to make this faster? I know most of the time is taken by the
y << orders.map { |o| o.quantity*op.find_by_offering_id(o.offering).quantity }.sum
line which calculates the number of products ordered in a given week. Any thoughts?
The problem is you're using iterations (i.e loops in application code) when you'd be better off using declarations (i.e. joins in the database). Loops will never be as fast as joins, and moving the dataset into the application's memory won't be helping either.
I'm guessing you're using ActiveRecord? If so, this may help with how to query with joins: http://guides.rubyonrails.org/active_record_querying.html
Here is what I ended up doing thanks to the info from Iain
def get_trend
sql = ActiveRecord::Base.connection()
if Rails.env == "production"
d=sql.execute("SELECT SUM(orders.quantity * offering_products.quantity), EXTRACT(ISOYEAR FROM orders.date) AS year, EXTRACT(WEEK FROM orders.date) AS week " +
" FROM orders " +
" INNER JOIN offerings ON offerings.id = orders.offering_id " +
" INNER JOIN offering_products ON offering_products.offering_id = offerings.id " +
" INNER JOIN products ON products.id = offering_products.product_id " +
" WHERE (products.id = #{self.id}) GROUP BY year, week ORDER BY year, week ")
y=d.map { |a| a["sum"].to_i }
else
d=sql.execute("SELECT SUM(orders.quantity * offering_products.quantity), strftime('%G-%V', orders.date) AS year " +
" FROM orders " +
" INNER JOIN offerings ON offerings.id = orders.offering_id " +
" INNER JOIN offering_products ON offering_products.offering_id = offerings.id " +
" INNER JOIN products ON products.id = offering_products.product_id " +
" WHERE (products.id = #{self.id}) GROUP BY year")
y=d.map { |a| a[0] }
end
return y
end
Update: needed to differentiate the code between production and local, because heroku uses postgresql, and the date functions work differently:( which also means the result isnt exactly the same, because the functions treat the first week of the year differently.
I need to run sql query like
sql = 'SELECT * FROM users WHERE id != ' + self.id.to_s + ' AND id NOT IN (SELECT artner_id FROM encounters WHERE user_id = ' + self.id.to_s + ')'
sql += ' AND id NOT IN (SELECT user_id FROM encounters WHERE partner_id = ' + self.id.to_s + ' AND predisposition = ' + Encounter::Negative.to_s + ')'
sql += ' AND cfg_sex = ' + self.sex.to_s + ' AND cfg_country = ' + self.country.to_s + ' AND cfg_city = ' + self.city.to_s
sql += ' ORDER BY rand() LIMIT 1'
It can be executed by AR.find_by_sql, but the code before is bad readable.
Are there any query builder, which can build that query?
For example, Kohana (it is PHP framework, I am php developer, but I want to change that kid-language to ruby/rails) have a query builder, which works like this:
$sql = DB::select('*')->from('users');
$sql->where('id', 'NOT_IN', DB::expr('SELECT partner_id FROM encounters WHERE user_id = '.$user->id));
$sql->where('id', 'NOT_IN', DB::expr('SELECT user_id FROM encounters WHERE partner_id = '.$user->id.' AND predisposition = '.Encounter::Negative));
....
etc
...
Query which was builded with query builder like a Kohana query builder is more readable and understandable.
Are there any gem to solve this problem?
You need the squeel gem. It extends AR with blocks and makes very complicated queries with ease.
Just few features:
# not_in == cool! )
Product.where{id.not_in LineItem.select{product_id}}
# SELECT "products".* FROM "products" WHERE "products"."id" NOT IN
# (SELECT "line_items"."product_id" FROM "line_items" )
# outer joins on pure Ruby:
LineItem.joins{product.outer}
# LineItem Load (0.0ms) SELECT "line_items".* FROM "line_items"
# LEFT OUTER JOIN "products" ON "products"."id" = "line_items"."product_id"
# calcs, aliasing:
Product.select{[avg(price).as(middle)]}
# SELECT avg("products"."price") AS middle FROM "products"
# comparison
Product.where{id != 100500}
Product.where{price<10}
# logical OR
Product.where{(price<10) | (title.like '%rails%')}
# SELECT "products".* FROM "products" WHERE (("products"."price" < 10 OR
# "products"."title" LIKE '%rails%'))
# xxx_any feature (also available xxx_all)
Product.where{title.like_any %w[%ruby% %rails%]}
# SELECT "products".* FROM "products" WHERE (("products"."title" LIKE '%ruby%' OR
# "products"."title" LIKE '%rails%'))
Note the using blocks: {...} here aren't hashes. Also note the absence of symbols.
If you decide to pick it, read the section that starts with "This carries with it an important implication"
There's a ruby library that utilizes relational algebra. It is called ARel. If you are using Rails 3.x, then you already have.
ids = Partner.where(user_id: self.id).pluck(:partner_id) << self.id
users = User.where("id NOT IN #{ ids.join(',') }")
Here's the same query cast into rails AREL terms. It's not pretty yet -- it's a complicated query in general.
User.where("id = ? AND "
"id NOT IN (SELECT artner_id FROM encounters WHERE user_id = ?) AND " +
"id NOT IN (SELECT user_id FROM encounters WHERE partner_id = ? AND predisposition = ? ) AND " +
"cfg_sex = ? AND cfg_country = ? AND cfg_city = ?)",
self.id, self.id, self.id, Encounter::Negative,
self.sex, self.country, self.city).order(" rand() ").limit(1)
(I've not tested this, so it's possible there could be typo's in it.)
I'd recommend a couple things:
When you have complex where clauses they can be chained together and AREL will put them back together generally pretty well. This allows you to use scopes in your model classes and chain them together.
For example, you could do this:
class User < ActiveRecord::Base
def self.in_city_state_country(city, state, country)
where("cfg_sex = ? AND cfg_country = ? AND cfg_city = ?", city, state, country)
end
def self.is_of_sex(sex)
where("cfg_sex = ?", sex)
end
end
Then you could rewrite these portions of the query this way:
User.is_of_sex(user.sex).in_city_state_country(user.city, user.state, user.country)
and so on.
Breaking the queries down into smaller parts also makes it easier to test specific pieces of it with your rspecs. It results in more modular, maintainable code.
For more details, check out the Rails Guide - Active Record Query Interface