Retrieving product count for each month in the current year laravel - laravel-8

I'm trying to count the number of orders for each month of the current year as follows
//month arrays to loop through
$month = ['1','2','3','4','5','6', '7', '8', '9', '10', '11','12'];
//current year
$year = Carbon::now()->year;
//variable to store each order coubnt as array.
$new_orders_count = [];
//Looping through the month array to get count for each month in the provided year
foreach ($month as $key => $value) {
$new_orders_count[] = Order::whereYear('updated_at', $year)
->whereMonth('updated_at',$value)
->where(['orders.status_id'=>11])
->orWhere(['orders.status_id'=>14])
->orWhere(['orders.status_id'=>4])->count();
}
This gives me the following result
Note that this is returning 48 even where it should return zero or a different value from 48, for example, months 6 through to 12 have no data thus I expect the query to return zero but it is not. Why is this and how can I achieve what I need? I'm using laravel's default timestamp format for the created_at and updated_at fields

//current year
$year = Carbon::now()->year;
//variable to store each order count as array.
$new_orders_count = [];
//Looping through the month array to get count for each month in the provided year
for($i = 1; $i <= 12; $i++){
$new_orders_count[] = Order::whereYear('updated_at', $year)
->whereMonth('updated_at', $i)
->where(function ($query) {
$query->whereIn('orders.status_id', [11, 14, 4]);
})->count();
}

Try like this way. change your query
Order::whereYear('updated_at', $year)
->whereMonth('updated_at', $value)
->where(function ($query) {
$query->whereIn('orders.status_id', [11, 14, 4]);
})->count();
may this help ...

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?

Laravel/SQL: where column Equals NOT and NULL

LARAVEL 5.4 (but probably it's a more general SQL question)
Hello! I have a table with a structure:
Suppose it's my model 'Table'.
I want a query which:
uses (receives) variables :
$id of array ['id', 'string', integer]
where string is '<' or '>'
$status_not_bad = bool;
(if true - include all rows where 'status' !== 'bad' AND 'status' IS NULL);
for example, we are given:
$id = [['id', '>', 0]];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id > 0" returns rows 1 and 3.
but if we given:
$id = [['id', '<', 3]];
$status_not_bad = true;
Table::thisquery() ... ->get();
"get rows where status is not bad and id < 3" returns row 1
(it should be same query which return those results using those variables).
Probably you end with something like this:
if ($status_not_bad) {
$nStatus = 'bad';
} else {
$nStatus = 'good';
}
Table::thisquery()->where('status', '<>', $nStatus)
->whereNotNull('status')
->where($id[0], $id[1], $id[2])
->get();
But it would be a good idea to check $id keys first.
Since row id = 3 you need <= in your where statement to have that row included in the result set
$id = ['id', '<=', 3];
So, I this works:
$chain = Sample::when($status_not_bad, function($query){
return $query->where('status', '<>', 'bad')
->orwhereNull('status');
})
->where([$id])
->get();

SQL group dates as week date

I have a table which contains func_id and date in format like (07.06.14 ). I am trying to create a function that returns the number of dates that is the week day of a date (07.06.14 ) and the func_id will equals the func_id that I will write. For example:
My table:
func_id 11 / date = 07.06.14
That will return 1 from 0. (Saturday code = 0);
I tried:
function Get_weekday($data){
$dat = explode(".",$data);
$date = date("l", mktime(0, 0, 0, $dat[0] , $dat[1], $dat[2]));
if($date == "Monday"){return 4;}
if($date == "Tuesday"){return 3;}
if($date == "Wednesday"){return 2;}
if($date == "Thursday"){return 1;}
if($date == "Friday"){return 0;}
if($date == "Saturday"){return 0;}
if($date == "Sunday"){return 0;}
}
function count_per_date($func_id,$day){
$result = mysql_query("SELECT COUNT(date) as data,date FROM entregas WHERE func_id = '$func_id' GROUP BY date");
while($row = mysql_fetch_assoc($result))
{
//That part I dont really know what to do
}}
Sorry for my english, I dont speak very well ):
You're looking for DAYOFWEEK
Example
SELECT DAYOFWEEK('2007-02-03');
Further info : DAYOFWEEK documentation

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.

Yii min date validation rule

How can I add a minimum date validation rule in a Model?
Example:
I have a column dt_ini as DATE, which I need to restrict the input as D+7, on create.
If today is: october 1st, 2012
the minimum valid date on create would be: october 8th, 2012.
Otherwise, I would throw a validation error as: Your date must be at least 7 days from now.
The code I would expect is something like this: (this is NOT tested, and probably won't work)
public function rules(){
return array('dt_ini', 'date', 'minDate' => '+7'),
}
Thanks.
Is this what you are looking for?
Create custom valid rule as follows:
class YourModel extends CActiveModel
{
// some....
public function rules(){
return array('dt_ini', 'dateValid', 'minDate' => '+7 day', 'on' => 'create');
}
public function dateValid($attribute, $params)
{
$valid=null;
$today = date('Y-m-d', time());
if(isset($params['minDate']))
$valid = date('Y-m-d', strtotime($params['minDate'])); //+7 day
if( !is_null($valid) )
{ //for increamental date
if($this->dt_ini > $valid || $this->dt_ini < $today )
$this->addError($attribute, 'enter error message');
}
}
}