grouping query result by month on the given period of time - php

hi im trying to get monthly sale of a online shop for a given period of time
i'm using unix epoch(time()) for storing sale date in the table
sold table looks like this
+-----------+---------------------+---------+----------+
| id | product_id | price | date |
+-----------+---------------------+---------+----------+
| 1 | 20 | 2000 |1323299365|
+-----------+---------------------+---------+----------+
| 2 | 28 | 3500 |1323297389|
+-----------+---------------------+---------+----------+
i want to findout monthly sale for a given period of time like
$from="3/2011";
$to ="4/2011";
i know how to change these dates to unix timestamp and get the result by something like that
//explode from
//$from = maketime(x,x,x,x,x);
//explode to
//$to= maketime(x,x,x,x,x);
$query = "select * from `sold_table` where date > $from and `date` < $to ";
but what i want is to group the results by month so i can have monthly statics
i know this query doesn't work but i want something like this
$query = "select sum(`price of each month`) from `sold_table` where date > $from and `date` < $to group by month ";
so i can have a result like
march(03) = 25000$;
april(04) = 200$ ;
i can group the result by every 30 days but i think there should be a cleaner way
maybe i can find out month between to epoch time like 1323299365 and 1323297389 and then get the monthly sale for each one of month ? but i dont know ho to extract month between two epoch time

Try something like this:
SELECT SUM(price), DATE_FORMAT(FROM_UNIXTIME(date), "%m") AS month FROM sold_table GROUP BY month
But be aware also of the year, you can use combination of month and year.

Related

Increase days automatically in database

I have an application where each user can request their vacations. There are two types of users, fixed and temporary. Fixed users have 24 days a year for vacations. The doubt comes with the temporary users.
Temporary users are added 2 days per month worked until December 31 of that year. For example:
user1 entered the company on 25/01/2019, until 31/12/2019 would have to increase it 2 days per month worked until that date, in total 22 days. As of 01/01/2020, those 2 days, will be increased every calendar month and start from 0, so that 01/01/2020 would have 0 days and 01/02/2020 would have 2 days.
Is there a PHP function or in MySQL a procedure for those 2 days to automatically add them to the database?
In the database I have a user table that has the following fields:
name available_days start_date
======= ================= ============
user1 0 25/01/2019
To those available_days is to which the days must be increased.
I have this function that calculates the difference in months since the user entered the company until today:
function difcurrentmonth($startdate){
$date = new DateTime($startdate);
$currentdate= (new DateTime)->format('Y-m-d H:i');
$finaldate = new DateTime($currentdate);
$dif = $date->diff($finaldate );
$month = ( $dif->y * 12 ) + $dif->m;
return $month;
}
$month = difcurrentmonth("2019-01-25");
$available_days= $month * 2;
Not quite an answer; too long for a comment...
-- Today is the 21st February 2019.
-- A temporary employee started work on 15th August 2018.
-- Accrued holiday resets on December 31st.
SELECT GREATEST('2018-08-15','2019-01-01') range_start
, '2019-02-21' range_end
, DATEDIFF('2019-02-21',GREATEST('2018-08-15','2019-01-01')) duration
, ROUND(DATEDIFF('2019-02-21',GREATEST('2018-08-15','2019-01-01'))/30,0) accrued;
+-------------+------------+----------+---------+
| range_start | range_end | duration | accrued |
+-------------+------------+----------+---------+
| 2019-01-01 | 2019-02-21 | 51 | 2 |
+-------------+------------+----------+---------+
In your scenario, '2018-08-15' would be replaced by a column from your database.
Firstly you will need to write a query that will get the available_days from the User table for user1.
I will assume you are using PDO for this example.
$stmt = $pdo_conn->prepare("UPDATE user SET available_days = available_days + 2 where [name] = :userName");
$stmt->bindParam(':userName', "user1");
$stmt->execute();
Create a cron job that runs on a certain day of the month. You might want to add the last_modified_date column to use as a safe catch to prevent updating the user multiple times within a given month.

Sum sql values based on distinct values from another column and put the result in array

I am trying to to create an array based on the results from sum values based on the distinct values from another column
I have these two columns Month and Lessons. In the column month is the month name when the lessons were given (January, February...). In the column lessons I have values like (12,7,6,9,11, etc.)
Example Values
Month |lessons
------------------
January |12
January |7
February |6
March |9
March |11
What I want to achieve is to sum all lessons for every month and then put the values in an array for example ($month_values = January Sum, February Sum, etc).
Example Result
$month_values = 19,6,20;
I have managed to get the months with this query
$sth = $db->prepare("SELECT DISTINCT month FROM acc where month!=''");
$sth->execute();
$result = $sth->fetchAll(PDO::FETCH_COLUMN, 0);
$months = json_encode($result);
But I am struggling to get the values for each month
I have searched here to see if anyone faced the same challenge, but couldn't find anything that can help me
Any suggestion how to alter the query above and to put the lessons values in a array?
Thanks
SELECT month, SUM(lessons)
FROM lessons_by_month
GROUP BY month
ORDER BY MONTH(STR_TO_DATE(month,'%M')) ASC
The above query will output you sum of lessons in the calendar month order.
SQLFIDDLE DEMO
select group_concat(month), group_concat(l) from (
SELECT month, SUM(lessons) as l FROM lessons_by_month GROUP BY month
) foo
Will give you
| GROUP_CONCAT(MONTH) | GROUP_CONCAT(L) |
|-----------------------|-----------------|
| February,January,June | 2,6,10 |
Simply, what you need in this case is to GROUP the rows by the month column.
SELECT month, SUM(lessons) AS lessons FROM lessons_by_month GROUP BY month
I also made an SQL Fiddle with which you can tweak around if you need to.
Here is an example output, based on the input from your question:
month | lessons
------------------
February | 6
January | 19
March | 20

Count records this month

I have a table that stores dates in the format of MM/DD/YY (field name is date). I need to have a count that totals just the records for the current month. From searching, this is what I currently have but something is not right. Do I need to do a convertToDate, is it that my field is called "date", or am I missing something entirely?
$totalcount = mysql_query("select count(*) as 'total'
FROM state_to_state
WHERE status = 99 AND type = 1
AND MONTH(`date`) = MONTH(CURDATE())
AND YEAR(`date`) = YEAR(CURDATE())");
$totalnum = mysql_fetch_array($totalcount);
if($totalnum['total'] > 0) { $month_status = $totalnum['total']." this Month. "; }
Your dates are NOT native mysql dates (varchar, probably?), so you cannot use the mysql date functions on them directly. date('MM/DD/YY') will not work reliably:
mysql> select month('03/03/14'), month('03/18/14');
+-------------------+-------------------+
| month('03/03/14') | month('03/18/14') |
+-------------------+-------------------+
| 3 | NULL |
+-------------------+-------------------+
Convert your date fields to native mysql date types, or take a huge hit on performance and convert them to native date values onthefly via str_to_date().

Highscores - Best time period for a user

I have a table which keeps track of data from a game, here is an example of the table:
id | player_name | date | score | kills
1 | test1 | 2013-01-01 00:00:00 | 10000 | 200
2 | test1 | 2013-01-01 00:01:00 | 12000 | 300
I have a leaderboards for players, it ranks people who gain the most score/kills, etc. in a certain time period. At the moment I have only got it so that it ranks players in the previous 24 hours. I am doing this by selecting the first and last records in a specified time period and then subtracting them to get the difference.
This is my current query:
SELECT date, score FROM datapoints WHERE player_name = :player AND date = (SELECT MIN(date) FROM datapoints WHERE player_name = :player AND date > DATE_SUB(CURDATE(), INTERVAL 24 HOUR))
UNION ALL
SELECT date, score FROM datapoints WHERE player_name = :player AND date = (SELECT MAX(date) FROM datapoints WHERE player_name = :player AND date > DATE_SUB(CURDATE(), INTERVAL 24 HOUR))
After subtracting I use the PHP arsort() function to order them and then display them on the page.
However, I want to add another feature. I want to be able to see the on which day was the users best day for score/kills.
I have been thinking of how I could possibly do it and one was was using the above query but having a loop for each day and taking out the best day, however this probably isn't very efficient and I was wondering, if there was a better way of doing this?
Here is how you would get the score changes and kills that occur on any given calendar day:
select date(date) as thedate, max(score) - min(score) as DayScore,
max(kills) - min(kills) as DayKills
from datapoints dp
where player_name = :player
group by date(date);
To get the top day for scores, for instance, you would add an order by and limit clause like this:
order by DayScore desc
limit 1;

from date to date - search and display

I have a database holding two bits of information. from date to date. I need this entry to appear in my calender on every day, but I can only manage to get to appear on the first and last date.
example of DB:
job_no | date1(from)| date2(to)
________________________________
1 |2013-01-28 | 2013-02-03
2 |2013-01-14 | 2013-01-18
Edit for question. the search bar I have allows for ONE date input and the the calender finds entries through date1 and the next 6 days.
I cannot have a search which contains two date inputs because my users are so used to this way and i do not want to increase searching time. I started to think that I had to find the dates between the dates, add that to an array then use an if statement to find matches...but even saying this makes no sense to me.
regarding job 1, I need my calender to show this job up on all dates 28/29/30/31/01/02/03.
My current search SELECT * FROM jobs WHERE date1='$searchinput' PER day and calender this search. I use strtotime to increase the input date by +1 to add to the search for each day.
Calender page.
What I want with my results. User searched Date 28th.
Mon 28 | Tues 29 | Wed 30 ...... | Fri 03 |
_________________________________________________________________________
Job no 1 | job no 1 | job no 1 ...... | job no 1
What I have now.
Mon 28 | Tues 29 | Wed 30 ...... | Fri 03 |
_________________________________________________________________________
Job no 1 | blank | blank | job no 1
each day has a new select query right now. It matches days with date 1 and date 2. I dont need this as before I only had jobs out on one day now they go out for more than one day and need the job to be noted on all days it is out by only using a job from date and job to date.
EDIT 2:
SELECT * FROM calender_db NATURAL JOIN job_db
WHERE section='two'
AND date1 < '$day' AND date2 > '$day'
OR date1 = '$day' OR date2 = '$day'
This query selects what I need, but as I am using OR the first WHERE CLAUSE can be null. I need that to always be in the clause. I have been looking at using IIF or CASE to rectify but do not how to implement 100%...?
why not use BETWEEN
SELECT * FROM tableName WHERE date BETWEEN 'date1' AND 'date2'
SQLFiddle Demo
UPDATE 1
SELECT *
FROM tableName
WHERE date BETWEEN '2013-01-28' AND '2013-01-28' + INTERVAL 6 DAY
SQLFiddle Demo
To generate a list of days between two dates:
$days = array();
$stop = strtotime($date2);
for ($current = strtotime($date1); $current <= $stop; $current = strtotime('+1 days', $current)) {
$days[] = date('d', $current);
}
echo join('/', $days);
Demo
Update
Misunderstood the question it seems, if both dates are stored as columns and you're querying with a single date:
SELECT *
FROM jobs
WHERE 'date_from_input' BETWEEN date1 AND date2
Update 2
Your latest query can be written as:
SELECT *
FROM calender_db NATURAL JOIN job_db
WHERE section='two' AND '$day' BETWEEN date1 AND date2
Try like this
SELECT * FROM Mytimetable WHERE date BETWEEN 'date1' AND 'date2'
Query between date1 - date2
SELECT *
FROM `objects`
WHERE (date_field BETWEEN '2013-01-30 14:15:55' AND '2013-02-19 10:15:55')
OR
SELECT *
FROM `objects`
WHERE (date_field BETWEEN date1 AND date2)
query to select dates between two dates with PHP variables.
i will explain with exapmle :
$date1 = "2013-02-19";
$date2 = "2013-02-25";
then sql query will be :
$query = " SELECT * FROM table_xyz where (date_item BETWEEN date('".$date1."') AND date('".$date2."')";
hope it solves your problem
SELECT
*
FROM
tablename
WHERE
date between '$date1' and '$date2'
order by
date

Categories