I am comparing two datetime in the SQL statement. This is done in PHP.
$result=mysqli_query($con,"SELECT
*
FROM
join
WHERE
join_date <= '$last_join_dates'
ORDER BY
join_date DESC LIMIT 3 OFFSET 3");
$last_join_dates gets update every time, so that I use offset to keep pulling in new data. However, comparing the date is not actually working.
Inside database: structure join_date looks like 2015-10-24 13:30:22 and it is a datetime type.
$last_join_datesI use is the exact same format 2015-10-26 08:23:22.
Since that doesn't work.. I tried the following to convert them.
TRIED FORMAT() the datetime, but does not work:
$result=mysqli_query($con,"SELECT
*
FROM
join
WHERE
FORMAT(join_date, 'yyyyMMddhhmmss') <= FORMAT($last_join_dates, 'yyyyMMddhhmmss')
ORDER BY
join_date DESC LIMIT 3 OFFSET 3");
TRIED Convert() the datetime, but doesn't seem to work either:
$result=mysqli_query($con,"SELECT
*
FROM
join
WHERE
REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(19), CONVERT(DATETIME, join_date, 112), 126), '-', ''), 'T', ''), ':', '') <= REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(19), CONVERT(DATETIME, $last_join_dates, 112), 126), '-', ''), 'T', ''), ':', '')
ORDER BY
join_date DESC LIMIT 3 OFFSET 3");
I'm not sure how to debug this.. Any suggestions?
well #1, JOIN is a mysql keyword so you need to either put back-ticks around it or better yet call your table something else
#2, this wouldn't be the reason it isn't working, but you should never use string interpolation like that, it is vulnerable to sql injection. Instead use $last_join_date as a bind variable: Bind variables in a mysql_query statement
The SQL you have above is correct, as seen below:
mysql> select * from test order by the_date;
+----+---------------------+
| id | the_date |
+----+---------------------+
| 1 | 2015-01-02 11:23:21 |
| 2 | 2015-01-03 12:23:21 |
| 3 | 2015-02-03 12:25:21 |
| 4 | 2015-02-05 12:25:21 |
| 5 | 2015-02-05 15:25:21 |
| 6 | 2015-02-05 15:37:21 |
| 7 | 2015-02-05 20:37:21 |
| 8 | 2015-02-05 20:37:40 |
| 9 | 2015-03-05 20:37:40 |
| 10 | 2015-03-06 20:37:40 |
+----+---------------------+
10 rows in set (0.00 sec)
mysql> select * from test where the_date <= '2015-02-10 01:12:24' order by the_date desc limit 3, 3;
+----+---------------------+
| id | the_date |
+----+---------------------+
| 5 | 2015-02-05 15:25:21 |
| 4 | 2015-02-05 12:25:21 |
| 3 | 2015-02-03 12:25:21 |
+----+---------------------+
3 rows in set (0.00 sec)
So try naming the table something else or use backticks "`". Also try running the query from the mysql command line. Maybe the data you have isn't what you thought but the query is working fine.
Try this one:
"SELECT * FROM join WHERE join_date <= '".date("Y-m-d H:i:s", strtotime($last_join_dates))."'ORDER BY join_date DESC LIMIT 3 OFFSET 3"
It converts $last_join_dates to a timestamp using strtotime, then the date function will convert it to the proper format.
Try this:
$result=mysqli_query($con,"SELECT
*
FROM
join
WHERE
UNIX_TIMESTAMP(join_date) <= '" . strtotime($last_join_dates) . "'
ORDER BY
join_date DESC LIMIT 3 OFFSET 3");
Related
I have a columns that has the time stamp when a row is created.
I need to find a way to get all the rows from the same 'day', and give each row a display number to show something like this:
+---------------------+
| order_date | // output should be:
+---------------------+
| 2016-05-11 13:01:41 | // 2016051101
| 2016-05-11 15:54:14 | // 2016051102
| 2016-05-11 17:16:18 | // 2016051103
| 2016-05-11 17:35:12 | // 2016051104
| 2016-05-11 17:55:16 | // 2016051105
| 2016-05-12 07:16:48 | // 2016051201
| 2016-05-12 09:30:57 | // 2016051202
| 2016-05-12 09:56:19 | // 2016051203
| 2016-05-13 11:27:21 | // 2016051301
| 2016-05-14 10:15:56 | // 2016051401
| 2016-05-15 11:35:07 | // 2016051501
| 2016-05-15 11:39:48 | // 2016051502
| 2016-05-15 11:40:12 | // 2016051503
+---------------------+
Can Mysql do this? or should the program, like php, handle this?
Final query I use:
SELECT t.order_date,
concat(
DATE_FORMAT(t.order_date, '%Y%m%d'),
LPAD(
(SELECT COUNT(*) FROM hz_order s WHERE s.order_date<= t.order_date AND DATE(s.order_date) = DATE(t.order_date)),
2,
0))display
FROM hz_order t
ORDER BY `display` ASC
Yes, you can do it with a correlated query, like this:
SELECT t.order_date,
concat(DATE_FORMAT(t.order_date, '%Y%m%d'),
(SELECT COUNT(*) FROM YourTable s
WHERE s.order_date<= t.order_date
AND DATE(s.order_date) = DATE(t.order_date)))
FROM YourTable t
This will generate the date as yyyymmdd+the count.
Yes, You can do this by -
SELECT CONCAT(DATE_FORMAT(date_field, '%Y%m%d'),
LPAD(COUNT(date_field), 2, '0'))
FROM table_name
GROUP BY DATE(date_field)
ORDER BY date_field DESC
DATE_FORMAT(date_field, '%Y%m%d') would format the date like yyyymmdd.
LPAD(COUNT(date_field), 2, '0') would generate a string with left padding (with 0) to 2 places with the count of that date.
Here's one way using MySQL. Other methods will be faster on larger data sets.
SELECT x.*
, CONCAT(DATE_FORMAT(x.order_date,'%Y%m%d'),LPAD(COUNT(*),2,0))oi
FROM my_table x
JOIN my_table y
ON DATE(y.order_date) = DATE(x.order_date)
AND y.order_date <= x.order_date
GROUP
BY x.order_date;
How can I get the latest data of a specific day in MySQL?
Let's assume that I have a column of dates recorded on my database
dates | time | value
---------------------------------------------
2015-08-05 | 11:03:02 | 200
2015-08-05 | 23:04:22 | 2400
2015-08-07 | 8:00:22 | 500
2015-08-08 | 13:00:11 | 400
2015-08-08 | 13:23:11 | 200
2015-08-09 | 17:00:23 | 2200
2015-08-09 | 17:06:00 | 1290
2015-08-09 | 19:22:00 | 900
2015-08-13 | 01:01:22 | 1010
I want to get the latest data or transaction of a specific date, my desired result would be like this
dates | time | value
---------------------------------------------
2015-08-05 | 23:04:22 | 2400
2015-08-07 | 8:00:22 | 500
2015-08-08 | 13:23:11 | 200
2015-08-09 | 19:22:00 | 900
2015-08-13 | 01:01:22 | 1010
Only the latest data of a spefic or distinct date is chosen, what is the possible query with this?
You need to do this way to get that for each dates
select t1.dates,t1.time,t1.value from table as t1 inner join
(
select dates,max(time) as time from table group by dates
) as t2 on t1.dates=t2.dates and t1.time=t2.time
Use
SELECT * FROM TABLE_NAME GROUP BY dates ORDER BY time desc LIMIT 1;
Or
SELECT * FROM TABLE_NAME GROUP BY dates HAVING time <= '23:59:59' LIMIT 1;
Try this:
SELECT `dates`, MAX(`time`) AS `time`, MAX(`value`) AS `value`
FROM `tbl_name`
GROUP BY `dates`
ORDER BY `dates` ASC
Try this query:
SELECT * FROM `table` GROUP BY dates ORDER BY time DESC;
This may be a little confusing but please bear with me. Here's the thing:
I have a database that contains ~1000 records, as the following table illustrates:
+------+----------+----------+
| id | date | amount |
+------+----------+----------+
| 0001 | 14/01/15 | 100 |
+------+----------+----------+
| 0002 | 14/02/04 | 358 |
+------+----------+----------+
| 0003 | 14/05/08 | 1125 |
+------+----------+----------+
What I want to do is this:
Retrieve all the records beginning at 2014 and until yesterday:
WHERE `date` > '14-01-01' AND `date` < CURDATE()
But also get the sum of amount up to the current date, this is:
WHERE `date` < CURDATE()
I've already got this working by just selecting all the records based on the second condition, getting the sum, and then excluding those which don't match the first condition. Something like this:
SELECT `id`, `date`, `amount` FROM `table`
WHERE `date` < CURDATE()
And then:
$rows = fetchAll($PDOStatement);
foreach($rows as $row) {
$sum += $row->amount;
if (
strtotime($row->date) > strtotime('14-01-01') &&
strtotime($row->date) < strtotime(date('Y-m-d'))
) {
$valid_rows[] = $row;
}
}
unset $rows;
Is there a way to achieve this in a single query, efficiently? Would a transaction be more efficient than sorting out the records in PHP? This has to be SQL-standard compliant (I'll be doing this on MySQL and SQLite).
Update:
It doesn't matter if the result ends up being something like this:
+------+----------+----------+-----+
| id | date | amount | sum |
+------+----------+----------+-----+
| 0001 | 14/01/15 | 100 | 458 |
+------+----------+----------+-----+
| 0002 | 14/02/04 | 358 | 458 |
+------+----------+----------+-----+
| 0003 | 14/05/08 | 1125 | 458 |
+------+----------+----------+-----+
The worst case would be when the resulting set ends up being the same as the set that gives the sum (in this case appending the sum would be irrelevant and would cause an overhead), but for any other regular cases the bandwith save would be huge.
You can create a special record with your sum and add it at the end of your first query
SELECT * FROM `table` WHERE `date` > '14-01-01' AND `date` < CURDATE()
UNION
SELECT 9999, CURDATE(), SUM(`amount`) FROM `table` WHERE `date` < CURDATE()
Then you will have all your desired record and the record with id 9999 or whatever is your sum
This could be achieved by correlated subquery, something like below:
SELECT *, (SELECT SUM(amount) FROM t WHERE t.date < t1.date) AS PrevAmount
FROM t AS t1
WHERE `date` > '14-01-01' AND `date` < CURDATE()
However it is very unefficient if the number of records is large.
It's hackish, but:
> select * from foo;
+------+------+
| id | val |
+------+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
+------+------+
5 rows in set (0.02 sec)
> select * from foo
left join (
select sum(val)
from foo
where id < 3
) AS bar ON 1=1
where id < 4;
+------+------+----------+
| id | val | sum(val) |
+------+------+----------+
| 1 | 1 | 3 |
| 2 | 2 | 3 |
| 3 | 3 | 3 |
+------+------+----------+
Basically, do your summing in a joined subquery. That'll attach the sum result to every row in the outer table's results. You'll waste a bit of bandwidth sending that duplicated value out with every row, but it does get you the results in a "single" query.
EDIT:
You can get the SUM using a LEFT OUTER JOIN.
SELECT t1.`id`, t1.`date`, t2.sum_amount
FROM
`table` t1
LEFT OUTER JOIN
(
SELECT SUM(`amount`) sum_amount
FROM `table`
WHERE `date` < CURDATE()
) t2
ON 1 = 1
WHERE t1.`date` > STR_TO_DATE('01,1,2014','%d,%m,%Y') AND t1.`date` < CURDATE();
This will do what you want it to do...optimizing the subquery is the real challenge:
SELECT id,date,amount,(SELECT SUM(amount) FROM table) AS total_amount
FROM table
WHERE date BETWEEN '14-01-01' AND DATE_ADD(CURDATE(), INTERVAL -1 DAY)
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
I have sql statement that works great in mysql, where I'm am using datediff. When I try to use it in php, I get an "mysql_fetch_arrary() expects parameter 1 to be a resource, boolean given in"
This the statement is...
$result = mysql_query("select hname, hsn, hmodel, hmake, htype, hwar, datediff(`hwar`, now()) from host where stype='physical';",$db);
I know the statement works in mysql
mysql> select hname, hsn, hmodel, hmake, htype, hwar, datediff(`hwar`, now()) from servers.host where stype='physical';
+--------------+---------+--------+-----------+-------+------------+-------------------------+
| hname | hsn | hmodel | hmake | htype | hwar | datediff(`hwar`, now()) |
+--------------+---------+--------+-----------+-------+------------+-------------------------+
| moscow | XXXXXXX | Dell | PowerEdge | R710 | 2013-09-13 | 225 |
| sydney | XXXXXXX | Dell | PowerEdge | R710 | 2013-09-15 | 227 |
When I remove datediff(hwar, now()), my page works. I wanted to use that as field
$datediff=$row['datediff'];
Any clues as to why it doesn't work?
try to make limit in your query
$result = mysql_query("select hname, hsn, hmodel, hmake, htype, hwar, datediff(`hwar`, now()) as dif from host where stype='physical' LIMIT 0,10 ;",$db);
look this post
Try with this:
Replace this piece of sql statement: datediff(hwar, now())
With: datediff(hwar, now()) as Diffdate
And recover it this way:
$datediff=$row['Diffdate'];
Bye XD
You should give the selector an alias:
select hname, hsn, hmodel, hmake, htype, hwar, datediff(`hwar`, now()) AS diff from host where stype='physical';
Then you could access the column with the name 'diff'