Display TIMEDIFF result from mySQL query to webpage - php

Me again, guys. The titles is pretty self-explanatory, but for the details:
I want to display the timediff(in hours) results on a webpage but I can't wrap my head around how to do it.
I'm using PHP and Codeigniter for this website.
So far, I have a mySQL database with a table named 'server_log' which looks like:
+--------+-----------+--------+---------+------------+-------------+
| log_id | host_name | status | host_id | profile_id | event_date |
+--------+-----------+-+----------------+------------+-------------+
| 1 | http://...| Online | 1 | 1 | *timestamp* |
+--------+-----------+--------+---------+--------------------------+
*It shows also other entries with status "Offline" and "Maintenance".
I have this query to get the entries per user (based on profile_id) w/c are also sorted by status ('Online','Offline', or 'Maintenance'):
SELECT * FROM server_log
WHERE (profile_id=$id AND status='Online')
AND event_date BETWEEN $from_date AND $to_date
ORDER BY event_date,host_id;
*the from_date and to_date are results from the webpage which lets the user choose a 'From' and 'To' date to filter the results like a report page.
The problem I have is that after the above query I do not know what I else I need in order to calculate the TIMEDIFF results for each server(host_id) then display them on the webpage. (I'd like to get the TIMEDIFF between the results after getting the query results for each status)
How do I get the TIMEDIFF result (integer)?
Simply put, I want the flow to be like this:
[1] After 1st query: (SELECT ALL 'Online' for $id)
log_id | host_name | status | host_id | profile_id | event_date
1 ping.test1 Online 1 2 **
2 ping.test1 Online 1 2 **
3 ping.test2 Offline 2 2 **
4 ping.test2 Offline 2 2 **
[2] After 2nd query: (loop for each host_id)
log_id | host_name | status | host_id | profile_id | event_date
1 ping.test1 Online 1 2 **
2 ping.test1 Online 1 2 **
-> then calculate diff_date of event_dates
---> then return value to be assigned to $data['reports_ping']
-----> back to [1] but selecting all 'Offline', then 'Maintenance'
-------> if all values are assigned, display $data['reports_ping'] as row (foreach)
I would like the results to show something like:
+------------+------------+------------+-------------+-------------+
| profile_id | host_name | online_hrs | offline_hrs | maintenance |
+------------+------------+------------+-------------+-------------+
| 1 | http://... | 2 | 1 | 0 |
+------------+------------+------------+-------------+-------------+
I'm relatively a beginner and not really that good with CodeIgniter, so any help with this would be REALLY appreciated. Thanks in advance!

TIMEDIFF meaning different time between event_date and now? Try this :
SELECT *, (event_date - NOW()) as TIMEDIFF FROM server_log
WHERE (profile_id=$id AND status='Online')
AND event_date BETWEEN $from_date AND $to_date
ORDER BY 'event_date','host_id';
-- EDIT --
Is this the logic you want?
$temp = null;
foreach($rows){
$event_date = "select event_date from server_log order by log_id LIMIT 1"; // specify this query using your CI format
$timediff = $event_date - $temp;
$temp = $event_date;
}

Related

Unable to fetch the accurate rooms availability in specific date range

Here is my database structure
Table name :set_inventory, and columns are below
inventory_id | room_id | quantity_start_date | quantity_end_date | total_rooms
1 | 2 | 2015-10-10 | 2015-10-12 | 5
2 | 2 | 2015-10-13 | 2015-10-14 | 10
3 | 2 | 2015-10-15 | 2015-10-17 | 0
Another Table
Table name : rooms, amd columns are
room_id | room_type | room_picture | room_description
2 | standard | pic_link | demo description
Description: In inventory table admin able to set the inventory based on multiple date ranges.
My query:
SELECT rooms.room_id, rooms.room_pic1, rooms.room_type, rooms.maximum_adults,
rooms.maximum_children, rooms.room_amenities,set_inventory.room_id,
set_inventory.quantity_start_date, set_inventory.quantity_start_date,
set_inventory.total_rooms
from rooms, set_inventory
WHERE rooms.room_id = set_inventory.room_id
AND quantity_start_date <= '2015-10-11'
AND quantity_end_date > '2015-10-13'
It shows me the inventory only 5, based in above query,
What i am looking for :actually, i am looking for the result,
for example my check_in_date "2015-10-11" and check_out_date is "2015-10-17"
In this i will be able to notify the customer that
"room is only available for 4 days,
Plz help me , thanks
UPDATED
Try this WHERE condition:
WHERE rooms.room_id = set_inventory.room_id AND DATE(quantity_start_date) <= '2015-10-11' AND DATE(quantity_end_date) > '2015-10-13';
So, minding you want to have the amount of days between these to dates, your query should contain somwthing like this:
SELECT ABS(DATEDIFF(a1.start_date, a2.end_date)) FROM (
SELECT quantity_start_date as start_date FROM set_inventory WHERE quantity_start_date <= '2015-10-11' ORDER BY start_date DESC LIMIT 1) a1, (
SELECT quantity_end_date as end_date FROM set_inventory WHERE quantity_end_date > '2015-10-13' ORDER BY end_date ASC LIMIT 1) a2;
If you try it, you'll get 4 in result.

Php Calender Week Random User Calculation

I got an database (phpmyadmin) in which I put users,
grid looks like this
+-----+---------+-----------------+----------------+
| id | user | categorie_bit | calender_week |
+-----+---------+-----------------+----------------+
| 1 | Kevin | 01 | 39 |
+-----+---------+-----------------+----------------+
the id and user is self explained. Categorie_bit stands for the current job he / she has to do like having a walk with the dog.
0 - no job
1 - job 1
10 - job 2
11 - both jobs
and the calender week shows the current calender week.
like this in php:
$date = new DateTime();
echo $date->format('W');
I got various users, each user has to do a job for this calenderweek for this instance 39.
The user is picked randomly from the database. (I used a PDO Wrapper)
$table = "users";
$columns = array("id", "firstname");
$orderBy = array('RAND()');
$result_set = $db->select($table,$columns, Null, Null, $orderBy, 1);
In the next step I give the user a "job".
Categorie_bit = 1.
The problem is now that I want to pick a user who did not have a "job" last calender week, so that all users are treated equally.
Edit:
How do I accomplish this for further usage, lets say user 1 had to work week 39 and user 2 for week 44 and so on...
My first idea is to change the random picker somehow.
Anyone knows how to accomplish this?
Just add a WHERE clause to your query checking if there's an entry last week for your user. I'm not familiar with your PDO wrapper but the resultant query should be:
SELECT u.id, u.firstname
FROM users u
WHERE (
SELECT COUNT(*)
FROM users u2
WHERE u.id = u2.id
AND u2.calendar_week = <?= $date->format('W') - 1 ?>
AND u2.categorie_bit > 0
) = 0
ORDER BY RAND()
LIMIT 1
UPDATE
To make sure each user wasn't assigned another job until every user had done a job at least once I would record the information differently. I would have two tables, one for users and one for the job they completed and the week they completed it on.
Users
+----+-------+
| id | user |
+----+-------+
| 1 | Kevin |
+----+-------+
Jobs
+----+--------+-----+------+
| id | userId | job | week |
+----+--------+-----+------+
| 1 | 1 | 01 | 39 |
| 2 | 2 | 10 | 39 |
| 3 | 6 | 01 | 40 |
| 4 | 8 | 10 | 40 |
+----+--------+-----+------+
Then you can use the following query:
SELECT u.id, u.user
FROM users u
LEFT JOIN jobs j ON u.id = j.userId
WHERE j.id IS NULL
ORDER BY RAND()
LIMIT 1
So now you only get users who haven't completed a job. Once everyone has completed a job and the query returns 0 results you just clear the jobs table and start afresh.

Php/mysql ranking system - Placement inside a result set ordered by column

In a blog-like website, all the users can "star" a news (= bookmark it, mark it as "favourite").
I have a mysql table for stats.
table_news_stats
id_news
total_stars (int) //Total number of users who starred this news
placement (int)
The placement field is intuitive: if you order all the news by the total_stars field you get each news placement. So, the news with most stars will be number 1, and so on.
So, suppose I have 700 records in my table_news_stats, and for each one I have the id and the total_stars count, how can I update the placement field automatically for each record? Which query is faster/better?
Example of the table_news_stats content:
First record (A):
1-3654-?
Second record (B):
2-2456-?
Third record (C):
3-8654-?
If you order the record by stars count:
the sequence of records is C - A - B
So... the result will be:
First record (A):
1-3654-2
Second record (B):
2-2456-3
Third record (C):
3-8654-1
Clarification:
why would I ever need the placement field at all?
It's pretty simple... the placement field will be populated by a cronjob the first day of every month. Basically it will provide a 'snapshot' of the rank of each news in terms of popularity (as it was at the beginning of the current month). As a consequence, thanks to the placement field, I will have the following information:
"The 1st day of this month the 'top starred' news list was like this:
1- News C
2- NewsA
3- News B "
Then, with a query "SELECT * FROM table_news_stats ORDER BY total_stars DESC" I can obtain the new ranking (in real-time).
As a consequence, I will have the following information:
"At the time the page is loaded, the 'top starred' news list is like this:
1- News A
2- News C
3- News B "
Finally, by comparing the two rankings, I obtain the last piece of information:
"News A has gained a position" +1
"News C has lost a position" -1
"News B has no change in position" +0
If there is a better way of doing this, let me know.
I guess you don't need to update the table just:
SELECT *
FROM table_news_stats
ORDER BY total_stars DESC
But if you want to know the place of each one you can:
SELECT *, IF(#idx IS NULL,#idx:= 1,#idx:= #idx+1)
FROM table_news_stats
ORDER BY total_stars DESC
And if you still need to update something like:
UPDATE table_news_stats
SET placement = FIND_IN_SET(id_news,(SELECT GROUP_CONCAT(t.id_news) FROM (SELECT id_news
FROM table_news_stats
ORDER BY total_stars DESC) t ))
SQLFiddle
Consider the following
mysql> select * from test ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 1 | 3 | 0 |
| 2 | 6 | 0 |
| 3 | 7 | 0 |
| 4 | 2 | 0 |
| 5 | 9 | 0 |
| 6 | 2 | 0 |
| 7 | 1 | 0 |
+------+-------------+-----------+
Now using the following you can update the placement as
update test t1 join
(
select *,
#rn:= if(#prev = total_stars,#rn,#rn+1) as rank ,
#prev:= total_stars
from test,(select #rn:=0,#prev:=0)r
order by total_stars desc
)t2
on t2.id = t1.id
set t1.placement = t2.rank ;
mysql> select * from test order by placement ;
+------+-------------+-----------+
| id | total_stars | placement |
+------+-------------+-----------+
| 5 | 9 | 1 |
| 3 | 7 | 2 |
| 2 | 6 | 3 |
| 1 | 3 | 4 |
| 4 | 2 | 5 |
| 6 | 2 | 5 |
| 7 | 1 | 6 |
+------+-------------+-----------+
Note that in case of tie will have the same placement.

Obtain the next times (in VARCHAR) from the DB in PHP, according to time now

i have this mysql table with the timetables the train with php,
Type (INT) | time_start | time_stop
1 | 09:31:00 | 09:34:00
1 | 09:43:00 | 09:47:00
1 | 09:55:00 | 09:58:00
1 | 10:07:00 | 10:10:00
1 | 10:33:00 | 10:36:00
1 | 10:45:00 | 10:47:00
1 | 10:57:00 | 11:00:00
1 | 11:12:00 | 11:15:00
1 | 11:35:00 | 11:38:00
(and it goes on..)
- "type" is the timetable type, cus it changes in the winter, summer, etc.
- "type" is INT, and "time_start" and "time_stop" are VARCHAR(8)
I would like to know the most efective way to get the 6 next "train times", acording to the time now.
Imagine, it's now 09:33:10, what I want to obtain is this ones:
1 | 09:43:00 | 09:47:00
1 | 09:55:00 | 09:58:00
1 | 10:07:00 | 10:10:00
1 | 10:33:00 | 10:36:00
1 | 10:45:00 | 10:47:00
1 | 10:57:00 | 11:00:00
If theres any change change i should do in the mysql table, i'm also open to your ideias.
Thanks in advance ;)
Miguel.
You simply could change the VARCHAR type to TIME type, and do a SQL request like
SELECT * FROM <yourtable> WHERE time_start > NOW()
The basic approach is this:
select *
from timetables tt
where tt.time_start > current time
order by tt.time_start
limit 6
There are two challenges with this. The first is midnight. Presumably, if the time is late in the evening, then you want trains in the early morning as well. The second is converting the times to the right format.
select *
from timetable tt
order by (t.time_start > time(now()) desc,
tt.time_start
limit 6
The trick is to move the where condition into the ordering clause. In effect, this starts the ordering at the current time and continues it after midnight. This allows you to select the six with wrapping.
The time() function should be doing the necessary conversion for the comparison.
Just convert your searched time to an int:
$char_time = '09:33:10';
$int_time = (int) str_replace(':','', $char_time);
and then construct your sql like this:
$sql = "SELECT *, CAST(REPLACE(time_start, ',', '') AS INT) as mytime
FROM yourtable WHERE mytime > $int_time
ORDER BY mytime LIMIT 6";
Basically what we do above is just casting your varchar time field to an int type, and using that for comparing, this is a good solution if you can't change your database fields to be of TIME type.
The query will be
SELECT * FROM table_name
WHERE time_start >=time(now())
LIMIT 6

Sort by YES OR NO

I have search for Articles with dates. In MySQL is:
Article:
id | title
1 | first
2 | second
3 | third
4 | fourth
DatesArticle:
id | article_id | from | to
1 | 1 | 10-10-2010 | 11-11-2010
2 | 2 | 11-10-2010 | 12-12-2010
3 | 1 | 13-12-2010 | 12-01-2012
4 | 3 | 11-11-2012 | 12-12-2012
5 | 4 | 02-02-2013 | 02-02-2014
i would like get all Article with dates and sort this by availability.
for example i would like get all Articles and SORT this by dates FROM 12-10-2011 TO 12-01-2012
this should return me:
first (is in range FROM TO - DatesArticle.id = 3)
third (is in range FROM TO - DatesArticle.id = 4)
second (is NOT in range FROM TO)
fourth (is NOT in range FROM TO)
Is this possible with SQL or SQL and PHP? If yes, how?
Use the clause CASE, something like:
SELECT * FROM DatesArticle
ORDER BY CASE
WHEN id=3 AND CURRENT_DATE()<=from and to < CURRENT_DATE()>=to THEN 1
WHEN <condition_2> THEN 2
etc...
ELSE <any other condition>
END
Not saying the above is going to work as it is but it gives you and idea. If you add an example of the query you have tried or how are you building your where clause it would help for better answer.
My idea was to when it's id= 3 assign 1, if id = 4 assign 2, any other value assign 3, after that make the where condition and order by the number that you assign.
Try this:
select *,
case when t1.id=3 then 1 when t1.id=4 then 2 else 3 end as t
from article as t1
join DatesArticle as t2
on t1.id=t2.id
where CURRENT_DATE()<=from
and to < CURRENT_DATE()
order by t
You must first JOIN the tables in order to access article's data.
Then you ORDER on a logical condition (if there's a date within the given range).
SELECT title
FROM Article JOIN DatesArticle
ON (Article.id = DatesArticle.id)
ORDER BY DatesArticle.from > LastDate AND DatesArticle.to < FirstDate DESC;
(I never get ASC and DESC right in logical sorts -- try and see what happens)

Categories