PHP Mysql order by time - php

categories and scheduler
categories
id name start_date end_date
1 cat1 2014-04-02 00:00:00 2014-04-12 10:00:00
2 cat2 2014-04-12 12:00:00 2014-04-12 13:00:00
3 cat3 2014-04-01 00:00:00 2014-04-12 11:00:00
and scheduler table is
id name firetime runonce
1 1 1397651700 1
2 1 1397652200 2
3 2 1397654100 2
like this. In scheduler table, name is categories table's id and firetime is strtotime of start_date and end_date. runonce called start_date and end_date reference.
If the firetime less than now date, it automatically deleted, but not categories. Here I want to sort by firetime which is ready for next fire. And fired categories should show below.
My query is:
SELECT * FROM categories ORDER BY sale_start_date, sale_end_date
Here, how to match with scheduler table and sort by upcoming fire date.

Try:
SELECT * FROM scheduler ORDER BY firetime

Your database has a very bad structure. Columns representing the same thing (date/time values) have different formats. Foreign key references have no name similarity (id, name).
I think you want a join and aggregation. Based on the information in your question, it is something like this:
SELECT c.*
FROM categories c join
scheduler s
on s.firetime between strtotime(sale_start_date) and strtotime(sale_end_date) and
s.name = c.id
ORDER BY sale_start_date, sale_end_date;

Related

Get total hours with PHP & MySQL

I have the following table
id | user_id | date | status
1 | 53 | 2018-09-18 06:59:54 | 1
2 | 62 | 2018-09-18 07:00:16 | 1
3 | 53 | 2018-09-18 09:34:12 | 2
4 | 53 | 2018-09-18 12:16:27 | 1
5 | 53 | 2018-09-18 18:03:19 | 2
6 | 62 | 2018-09-18 18:17:41 | 2
I would like to get the total working hours (from date range) and group them by user_id
UPDATE
The system does not "require" a check-out so if there is only one value can we set a default check out time lets say 19:00:00? IF not I can check every day at 21:00:00 if there is not a checkout time to manually insert it at 19:00:00
UPDATE 2
I have added a new field in the table "status" so the very first check-in of the date the status = 1 and every 2nd check-in the status = 2
So if a user check-ins for the 3rd time during the day the status will be 1 again etc.
I hope this will make things easier
Thanks
In case of multiple check-in and check-out happening within a day, for a user:
Utilizing Correlated Subquery, we can find corresponding "checkout_time" for every "checkin_time".
Also, note the usage of Ifnull(), Timestamp() functions etc, to consider default "checkout_time" as 19:00:00, in case of no corresponding entry.
Then, considering this enhanced data-set as Derived Table, we group the data-set based on the user_id and date. Date (yyyy-mm-dd) can be determined using Date() function.
Eventually, use Timestampdiff() function with Sum aggregation, to determine the total work seconds for a user_id at a particular date.
You can easily convert these total seconds to hours (either in your application code, or at the query itself (divide seconds by 3600).
The reason I have preferred to compute using seconds, as Timestampdiff() function returns integer only. So there may be truncation errors, in case of multiple checkin/checkout(s).
Use the following query (replace your_table with your actual table name):
SELECT inner_nest.user_id,
DATE(inner_nest.checkin_time) AS work_date,
SUM(TIMESTAMPDIFF(SECOND,
inner_nest.checkin_time,
inner_nest.checkout_time)) AS total_work_seconds
FROM
(
SELECT t1.user_id,
t1.date as checkin_time,
t1.status,
IFNULL( (
SELECT t2.date
FROM your_table AS t2
WHERE t2.user_id = t1.user_id
AND t2.status = 2
AND t2.date > t1.date
AND DATE(t2.date) = DATE(t1.date)
ORDER BY t2.date ASC LIMIT 1
),
TIMESTAMP(DATE(t1.date),'19:00:00')
) AS checkout_time
FROM `your_table` AS t1
WHERE t1.status = 1
) AS inner_nest
GROUP BY inner_nest.user_id, DATE(inner_nest.checkin_time)
Additional: Following solution will work for the case when there is a single check-in, and corresponding check-out on the same date.
You first need to group the dataset based on the user_id and date. Date (yyyy-mm-dd) can be determined using Date() function.
Now use aggregation functions like Min() and Max() to find the starting and closing time for a user_id at a particular date.
Eventually, use Timestampdiff() function to determine the working hours for a user_id at a particular date (difference between the closing and starting time)
Try the following query (replace your_table with your actual table name):
SELECT user_id,
DATE(`date`) AS working_date,
TIMESTAMPDIFF(HOUR, MIN(`date`), MAX(`date`)) AS working_hours
FROM your_table
GROUP BY
user_id,
DATE(`date`)
Use TIMESTAMPDIFF function
the query more like :
SELECT t1.user_id, TIMESTAMPDIFF(HOUR,t1.date,t2.date) as difference
FROM your_table t1
INNER JOIN your_table t2 on t1.user_id = t2.user_id
Group By t1.user_id
You can see this as preference TimeStampDiff

Select distinct by highest or lowest value

I'm working on a track and field ranking database in MySQL/PHP5 whereby I'm struggling to find the best way to query results per unique athlete by highest value.
just
SELECT distinct name, event
FROM results
sample database
name | event | result
--------------------------
athlete 1 | 40 | 7.43
athlete 2 | 40 | 7.66
athlete 1 | 40 | 7.33
athlete 1 | 60 | 9.99
athlete 2 | 60 | 10.55
so let's say that in this case I'd like to rank the athletes on the 40m dash event by best performance I tried
SELECT distinct name, event
FROM results
WHERE event = 40
ORDER by result DESC
but the distinct only leaves the first performance (7.43) of the athlete which isn't the best (7.33). Is there an easy way other than creating a temp table first whereby the results are ordered first and performing a select on the temp table afterwards?
You might be interested in group by:
SELECT name, min(result) as result
FROM results
WHERE event = 40
GROUP BY name
This gives you the best result per athlete.
As suggested by spencer, you can also order the list by appending this:
ORDER BY min(result) ASC
The problem is that the columns used in the ORDER BY aren't specified in the DISTINCT. To do this, you need to use an aggregate function to sort on, and use a GROUP BY to make the DISTINCT work.
SELECT distinct name, event
FROM results
WHERE event = 40
GROUP BY name
ORDER by result DESC

How do I order by one column and then push latest chunk of same column id's to top?

For example I have table:
| id | title | created_at |
1 12:00
2 13:00
2 14:00
1 15:00
I want same id numbers to be near each other. In this case 1 1 2 2 or 2 2 1 1 AND order same chunks of id's by created_at time so the chunk of id's which own the latest created_at stays on top, then goes one, having highest created_at compared to 3rd chunk of id's and so on. How do I do it?
orderBy('id', 'desc')->orderBy('created_at', 'desc')->get(); // orders id's to same id chunks, but it doesn't sort that the chunk with latest id chunk (1 1) created_at at the top.
orderBy('created_at', 'desc')->orderBy('id', 'desc')->get(); // gives the latest created_at at top and so on, but same id's arent close to each other.
Bigger example:
| id | title | created_at |
1 12:00
2 13:00
1 15:00
2 15:00
1 17:00
3 18:00
1 19:00
3 20:00
Want to anchieve that foreach($table_rows as $row) { } would give me result:
3 20:00
3 18:00
1 19:00
1 17:00
1 15:00
1 12:00
2 15:00
2 13:00
I know it's hard to do with mysql alone. How do I do this in php easiest way?
I bet I have to sort by id first and then push each id's chunk relative to each other by latest created_at.
You need to get the information of the most recent date for each id. Here is a method using join and an aggregation:
select t.*
from table t join
(select t.id, max(created_at) as maxca
from table t
group by t.id
) tt
on t.id = tt.id
order by tt.maxca desc, id;
The rest is just the order by using the maximum value.
I don't know how to express this in laravel, but your question is also tagged mysql.

SQL getting monthly totals from table

I have a table with prices, date as a timestamp, the month of entry and the year of entry.
+++++++++++++++++++++++++++++
Price | Date | Month | Year |
+++++++++++++++++++++++++++++
9.00 |343345| 2 | 2013 |
3.00 |343445| 2 | 2013 |
4.00 |343245| 1 | 2013 |
1.00 |342245| 1 | 2013 |
5.00 |333355| 12 | 2012 |
So far I have this to list the monthly price totals, the problem is GROUP BY re-sorts the results so that it goes month 1, month 12 then month 2 where as I need the results to descend from the current month, month-by-month.
"SELECT month,SUM(price), FROM table GROUP BY month ORDER BY date DESC "
I'm using PHP if that helps.
It's treating your month as text instead of numeric. Cast it as an integer and it'll sort properly.
SELECT CAST(Month as int) as Month, SUM(PRICE), FROM table Group by month ORDER BY CAST(MONTH as int) desc
The problem is your date field is not stored as a datetime. Instead of ordering by it, order by your year and month fields instead (I presume you want to group by both of those fields).
SELECT year,month,SUM(price)
FROM table
GROUP BY year,month
ORDER BY year DESC, month DESC
If the year and/or month are stored as varchar, then cast them -- I suspect those are stored as integers though:
Cast your month to INT data type:
SELECT month,SUM(price), SUM(price), FROM table GROUP BY month ORDER BY cast(month as UNSIGNED) DESC
More: CAST
I had similar problem. I solved it by adding another column with 'date' type and convert all the different fields in dates. Then you can make selects within time range.

compare between two dates

i have a course table and a course due dates table like this
course_id | course_name
1 A
2 B
due_id | start_date | end_date course_id
1 2011-02-01 2011-02-28 1
2 2011-03-01 2011-03-15 1
now what i am trying to do from last tow day that write a query or code that will show a course name with current date session.for example if current date is betwen start and end date course should come like this and if its in next date session it should come with next due_id
course_id | course_name | due_id
1 A | 1
if this database structure is wrong for this please let me know
thanks for help
SELECT course.course_name, due_dates.course_id, due_id
FROM course
INNER JOIN due_dates ON course.course_id = due_dates.course_id
WHERE now() BETWEEN start_date and end_date;

Categories