Grouping Whole records by formatted Date Hash - ruby-on-rails-3

I am trying to get these querys to return a hash that has id's like this:
{[08/14/2015, [... records ...]],[08/15/2015, [... records ...]]}
With the following code it does this:
#trucks = Truck.where(:company_id => 33)
#trucks_by_date = #trucks.group_by(&:available)
=> {[Fri, 14 Aug 2015 00:00:00 UTC +00:00, [... records ...]], [Sat, 15 Aug 2015 00:00:00 UTC +00:00, [... records ...]]}
I have tried this but it errors:
#trucks.group_by("CAST(available AS DATE)")
--- AND ---
#trucks.group("DATE(available)")
=> 1.9.3-p551 :074 > #trucks_by_date = #trucks.group("DATE(available)")
Truck Load (74.2ms) SELECT "trucks".* FROM "trucks" WHERE "trucks"."company_id" = 33 GROUP BY DATE(available)
ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "trucks.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "trucks".* FROM "trucks" WHERE "trucks"."company_id"...
^
: SELECT "trucks".* FROM "trucks" WHERE "trucks"."company_id" = 33 GROUP BY DATE(available)
from /usr/local/rvm/gems/ruby-1.9.3-p551#loadmax/gems/activerecord-3.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:1139:in `async_exec'
from /usr/local/rvm/gems/ruby-1.9.3-p551#loadmax/gems/activerecord-3.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:1139:in `exec_no_cache'
from /usr/local/rvm/gems/ruby-1.9.3-p551#loadmax/gems/activerecord-3.2.3/lib/active_record/connection_adapters/postgresql_adapter.rb:663:in `block in exec_query'
If i do this: (also wrong format for date)
#trucks_by_date = #trucks.group("DATE(available)").count
=> `{"2015-08-13"=>5, "2015-07-27"=>3, "2015-08-18"=>2, "2015-08-14"=>6, "2015-08-17"=>1, "2015-07-31"=>2, "2015-08-12"=>5, "2015-08-11"=>8, "2015-07-30"=>4, "2015-08-10"=>13, "2015-08-07"=>4, "2015-08-03"=>4, "2015-07-24"=>1, "2015-07-28"=>5}`
But i don't want counts i want complete records.
REASON: I have a initializer that changes formats on data like so:
Date::DATE_FORMATS[:default] = "%m/%d/%Y"
Time::DATE_FORMATS[:default] = "%m/%d/%Y"
and when i try to iterate thru the hash it changes the formats so it cant find the right position of the hash

#trucks = Truck.where(:company_id => 33)
#trucks_by_date = #trucks.group_by {|t| t.available.to_s(:default) }

Related

select, group, sum with ASP LINQ + private compare method

i am working on an ASP MVC Project and i have a part where i need to export some data to an excel file. the thing is that i need to sum some rows to display a single row. I am not familiar with sql or linq and i am struggling to get the result i want.
there should be 4 columns: requester(string), date(datetime), collection(string), timeinvested(int).
the grouping should be by the column 'collection' (string) as default and if the filter input for requester or date was filled than that would be the next level of grouping. the column 'timespent' should be summarized by the result of the grouping.
example:
requester, date, collection, timeinvested
(1) john, jan 1st, 2019, collection1, 1
(2) mike, jan 1st, 2019, collection1, 3
(3) eric, jan 1st, 2019, collection1, 2
(4) july, jan 1st, 2019, collection2, 5
(5) john, jan 1st, 2012, collection1, 3
here we have 5 rows from the table, once we filter to export only by default (column collection) then rows 1+2+3+5 should sum to 1 row and the 2nd row will be row 4, because the collections are different. like so:
requester, date, collection, timeinvested
(1) john, jan 1st, 2019, collection1, 9
(2) july, jan 1st, 2019, collection2, 5
if i choose to filter also by requester or date then it should apply accordingly.
one big thing here is that there is a private method that checks the date to a particular date and it should export to the file the date year if its after or before the checked date. for example: relative date dec 1st of the same year
if the row date is before relative date then we should write date year - 1;
thanks
var q = (from a in items
select new {
Requester = a.Requester.Name,
Collection = a.Collection.Name,
TimeSpent = a.TimeSpent,
Year = a.Date,
})
.ToList()
.GroupBy(x => new {
x.Requester,
x.Collection,
x.Year,
x.TimeSpent
})
.Select(y => new CollectionModel {
Requester = y.Key.Requester,
Collection = y.Key.Collection,
TimeSpent = y.Sum(z => Convert.ToInt32(z.TimeSpent)),
Year = checkDate(y.Key.Year),
});
return q.ToList();
this is how i made it work:
var q = (from a in items
select new {
Requester = a.Requester.Name,
Collection = a.Collection.Name,
TimeSpent = a.TimeSpent,
Year = a.Date,
})
.Where(Where(a => dt == null || (dt != null && a.Year == dt.Year))
.ToList()
.GroupBy(x => new {
x.Requester,
x.Collection,
x.Year,
})
.Select(y => new CollectionModel {
Requester = y.Key.Requester,
Collection = y.Key.Collection,
TimeSpent = y.Sum(z => Convert.ToInt32(z.TimeSpent)),
Year = checkDate(y.Key.Year),
});
return q.ToList();
First, remove the "x.TimeSpent" from your GroupBy, you need to aggregate that variable, not group by it. secondly, could you post the output as well?

Convert SQL Server query to Entity Framework query

I have a SQL Server query like this:
select
month(fact_date) as month,
sum(case when beef_dairy_stat = 1 and param_id = 1 then 1 else 0 end) as cnt
from
user_behave_fact
where
YEAR(fact_date) = 2018
group by
month(fact_date)
order by
month
with a result of
month cnt
------------
1 10
2 20
Now I need to convert this query to its corresponding Entity Framework query.
This is my current attempt:
var sql_rez_ICC = new List<Tuple<int, int>>();
sql_rez_ICC = db.user_behave_fact
.Where(x => x.fact_date.Value.Year == selected_year)
.GroupBy(y => y.fact_date.Value.Month)
.Select(y =>new { month = y.Select(x=>x.fact_date.Value.Month), icc_count = y.Count(x => x.beef_dairy_stat == true && x.param_id == 1) })
.AsEnumerable()
.Select(y => new Tuple<int, int>(y.month, y.icc_count))
.ToList();
However on second .Select, I get an error on month which is
Cannot convert from System.Collection.Generic.IEnumrable to int
y.Select(x=>x.fact_date.Value.Month) returns an IEnumerable<int>. Use y.Key instead.

Pig Sum field from bag not works

Updated
The input is a json line text file.
{"store":"079","items":[{"name":"早晨全餐","unit_price":18,"quantity":1,"total":18},{"name":"麦趣鸡盒","unit_price":78,"quantity":5,"total":390},{"name":"巨无霸","unit_price":17,"quantity":5,"total":85},{"name":"香骨鸡腿","unit_price":12,"quantity":2,"total":24},{"name":"小薯条","unit_price":7,"quantity":5,"total":35}],"date":"\/Date(1483256820000)\/","oId":"27841ef9-f88e-478f-8f20-17c3ad090ebc"}
{"store":"041","items":[{"name":"小薯条","unit_price":7,"quantity":2,"total":14},{"name":"巨无霸","unit_price":17,"quantity":4,"total":68}],"date":"\/Date(1483221780000)\/","oId":"afee2e6d-0f81-4780-82e9-2169bf3c43f3"}
{"store":"008","items":[{"name":"奶昔香草","unit_price":9,"quantity":5,"total":45},{"name":"小薯条","unit_price":7,"quantity":2,"total":14}],"date":"\/Date(1483248600000)\/","oId":"802ea077-1eef-4cc9-af89-af7398e56792"}
Expect to group by all store and calculate the sum of total in each items,for example:
store_name total_amount
_________________________
001 2212.26
002 3245.46
003 888888
My Pig script:
store_table = LOAD '/example/store-data/2017-store-sales-data.json'
USING JsonLoader('
store_name:chararray,
items: {(
name:chararray,
unit_price:Bigdecimal,
quantity:int,
total:Bigdecimal)
},
date:Datetime,
oId:chararray'
);
platten_table = foreach store_table generate flatten(items), store_name;
store_group = group platten_table by store_name;
result = foreach store_group {
total_sum = sum(platten_table.items::total);
Generate group,total_sum;
}
Pig error is :
2017-11-28 08:53:54,357 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1200: mismatched input 'Generate' expecting SEMI_COLON
Eval Functions are case sensitive, you need to use the eval function SUM in upper case.
Code snippet -
result = foreach store_group {
total_sum = SUM(platten_table.items::total);
Generate group,total_sum;
}
Refer : https://pig.apache.org/docs/r0.10.0/basic.html

Why is my 'WHERE' clause based on a 'DATE' failing?

I'm using node.js to connect to an SQL database (SQL Server 2016 specifically). My table, called transactionCounts, has the following tables and data types:
staff_id: varchar(50), date: Date, count: int;
The 'date' field is just a date, not a DateTime, for clarity. Records look like this: "2017-08-07"
I'm using the mssql package, const sql = require('mssql');
So basically, I have a function which accepts a start date and an end date and does this with them:
function(start, end) {
let ps = new sql.PreparedStatement(transactionRegisterSqlPool);
ps.input('start', sql.Date);
ps.input('end', sql.Date);
ps.prepare('SELECT staff_id, SUM(Count) TotalCount FROM [TransactionRegister].[dbo].[transactionCounts] ' +
'WHERE date >= #start AND date < #end GROUP BY staff_id', err => {
.execute({start: start, end: end}, (err, result) => {});
});
};
I've simplified the function for illustrations sake (it normally returns a promise), but here's what's going wrong:
I pass in the dates of Aug 20 midnight, and Aug 27 midnight, and what I'm expecting to get back is the sum for the dates 20,21,22,23,24,25 and 26 naturally (7 days, a week).
26th isn't being included though (definitely), and I'm not entirely sure but I'd wager that the 19th is being included. I think it's a daylight-savings issue, because these dates, when i call .toISOString(), look like 2017-08-19T23:00:00.000Z and 2017-08-26T23:00:00.000Z respectively (11pm the night prior).
I've modified my function to use strings instead of dates, and this seems to work and returns the correct Sums:
function(start, end) {
let ps = new sql.PreparedStatement(transactionRegisterSqlPool);
ps.input('start', sql.VarChar);
ps.input('end', sql.VarChar);
start = `${start.getFullYear()}/${start.getMonth() + 1}/${start.getDate()}`;
end = `${end.getFullYear()}/${end.getMonth() + 1}/${end.getDate()}`;
ps.prepare('SELECT staff_id, SUM(Count) TotalCount FROM [TransactionRegister].[dbo].[transactionCounts] ' +
'WHERE date >= #start AND date < #end GROUP BY staff_id', err => {
ps.execute({start: start, end: end}, (err, result) => {});
});
};
But it seems...wrong to take my dates and turn them into strings to work my way around this issue. What is the correct way to deal with dates between Javascript Dates and SQL Dates, so that this apparent Daylight-Savings-caused issue is avoided?
Your problem is that JavaScript does not have a "date" type, only "datetime", yet SQL does have a "date" type. Because of that, you will have to do the conversion.
If you wrap it in a function, it is still readable:
function toDateString(d) {
return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`;
}
ps.prepare('SELECT staff_id, SUM(Count) TotalCount FROM [TransactionRegister].[dbo].[transactionCounts] ' +
'WHERE date >= #start AND date < #end GROUP BY staff_id', err => {
ps.execute({start: toDateString(start), end: toDateString(end)}, (err, result) => {});
});

Optimize SQL query that retrieves count of items over a period

Is there a way to better optimize the query in this function? I am wanting it to only make a single SQL query if possible. The code picks up the number of events generated over 2 weeks. Thanks.
def items_chart_data
#current_student = Student.find(current_user.student_id)
(2.weeks.ago.to_date..DateTime.now).map do |date|
{
created_at: date,
item_count: Item.where("date(created_at) = ? AND student_id = ?", date, #current_student.id).count
}
end
end
You can do it in one query, like this:
items = Item.select('date(created_at) as date_created, count(id) as id_count').
where('student_id = ? and created_at >= ?', current_user.student_id, 2.weeks.ago.beginning_of_day).
group('date(created_at)').map do |item|
{ created_at: item.date_created, item_count: item.id_count }
end
To get the missing dates with 0 items into your array you can do this:
(2.weeks.ago.to_date..Date.current).each do |date|
date = date.strftime('%Y-%m-%d')
unless items.any? { |h| h.value?(date) } # Check if date exists already
items << { created_at: date, item_count: 0 } # Add item_count: 0 if not
end
end
items.sort_by! { |h| h[:created_at] } # Put array in correct order
Note that adding the zero item days to the array doesn't perform any queries. The array items contains only 14 elements, so (especially compared to querying the database 14 times) this code should be really fast.