I am trying to make a query about joining showingdates and showings table and get all the showings for a date and order them by time.
My showingdates dayfield is formed as showdate(datetime) and shows "2013-03-06 00:00:00"
My showings performance_date field is again a datetime and examples are
"2013-03-06 20:00:00 ,
"2013-03-06 21:00:00" .
How can I make a query for that date and order them by time ?
This should work.
SELECT garbage
FROM trash
WHERE DATE(showdate) = '2013-03-06'
ORDER BY TIME(showdate) DESC
The time here is descending. Remove DESC to achieve ascending order.
To get rows only from a specific date (no use of any function on the showdate column, so indexes can be used):
WHERE showdate >= '2013-03-06'
AND showdate < '2013-03-06' + INTERVAL 1 DAY
To order by time (since all rows will have the same date, and the showdate has both date and time, simply order by that):
ORDER BY showdate
Related
I use MariaDB and have a table where each row has a date and a score.
I want to first show the rows where the date is 3 days old or newer, sorted by the score - then show the rest (more than 3 days old) sorted by date.
Since my date is stored in unix time, it's fairly easy to have php calculate 3 days from before now and use that as my $scoreTimeLimit variable in the below:
Here are my two queries:
SELECT * FROM myTable WHERE myDate > $scoreTimeLimit ORDER BY myPopularityScore DESC
SELECT * FROM myTable WHERE myDate < $scoreTimeLimit ORDER BY myDate DESC
However, I would VERY much like to have only 1 query instead of two. Can it be done...?
This is a job for UNION.
SELECT * FROM (
SELECT 0 ord1, NOW() as ord2, *
FROM myTable WHERE myDate > NOW() - INTERVAL 3 DAY
UNION ALL
SELECT 1 ord1, myDate as ord2, *
FROM myTable WHERE myDate <= NOW() - INTERVAL 3 DAY
) a
ORDER BY ord1, ord2 DESC, myPopularityScore
The inner query gives you a single result set with a couple of extra columns added on to help you manage your sorting.
I am having so much trouble with this. I am trying to get the maximum value per day given the range. But I keep getting a blank value in my count column when I load the query result.
<?php
include("dbconnect.php");
$link=Connection();
$data1 = '2016-04-29 00:00:00';
$data2 = '2016-05-02 00:00:00';
$result = mysql_query(
"
SELECT DATE(orderDate), MAX(Count)
FROM testLocation
WHERE orderDate
BETWEEN '$data1%' AND '$data2%'
GROUP BY DATE(orderDate)
"
,$link
);
?>
A few things to look at here.
First, the % signs in your date constants should not be there. Those only work with the LIKE operator.
Second, the BETWEEN operator works poorly for DATETIME values, because it is the equivalent of this:
WHERE orderDate >= '$data1'
AND orderDate <= '$data2' -- wrong!
This excludes everything after precisely midnight on the ending date. <= is the wrong comparison to use for DATETIME.
You should use this instead:
WHERE orderDate >= '$data1'
AND orderDate < '$data2' + INTERVAL 1 DAY
It includes everything up until, but not including, < midnight on the day after the end date you gave. That means it will include everything on the last day of your date range, which is presumably what you want.
Third, I suggest you give alias column names to the columns in your result set. That will make them easier for php code to retrieve.
SELECT DATE(orderDate) orderDate,
MAX(Count) maxCount
FROM testLocation
WHERE orderDate >= '$data1'
AND orderDate < '$data2' + INTERVAL 1 DAY
GROUP BY DATE(orderDate)
Fourth, if your testLocation table has no records in it at all for a particular date, the result set from this query will omit that date.
Fifth (others mentioned this in comments) the mysql_ API is not a good choice for your php programming; it's insecure.
I suggest you to please use PDO for the above queries.Your question is not fully clear but if you intend to retrieve database result whose value is maximum you can do the following way.
$sql='SELECT * FROM testLocation
WHERE orderDate
BETWEEN '$data1%' AND '$data2%' ORDER BY orderDate
DESC LIMIT 1';
By this query we have limited the retrieved data to be 1 and that is why you will get only the maximum value here and mark we have ordered the data in descending manner.
I have a column(cradit_end_date) that it specifies a product is expire or not.
this column have two states :
0000-00-00 00:00:0 <= this means this product has no expiration date.
A date (ex: 2014-10-24 10:00:00) <= this means this product has a expiration date (here almost a month later).
now, how can I get products that are both no expiration date and is not expired ?
Is it possible with PHP or SQL?
(I am using mysql).
$result_coupons = mysql_query("select id,title,pic,price,off,fake_sell,cradit_end_date from coupons where
confirm=2 and status=1 and
shop_id=$row->id ORDER BY id DESC limit 1");
You could check for multiple states in the single column using an OR operator.
...
WHERE (cradit_end_date = '0000-00-00 00:00:00' OR cradit_end_date > NOW())
...
I have the following dates in my table. How do I find a closest date from either today (if today's date is there) or if today's date is not there then the nearest past date?
2012-10-01 aa123
2012-10-02 aa43
2012-10-03 aa478
2012-10-04 aa40
2012-10-05 aa54
2012-10-06 de34
2012-10-07 a5434
2012-10-08 r4t
2012-10-09 x34
2012-10-10 q23
2012-10-11 b53
So if today is '2012-10-07' is then the record will be a5434. But if 2012-10-07 is missing then the record will be de34 which belongs to 2012-10-06 since that would be the closest past day from today.
I am not sure where to start on this one, so I haven't tried anything yet. Need a sql solution to this.
It's simple, just get one of the last date <= the current date:
$now = date("Y-m-d");
$sql = "SELECT * FROM date_table where date_field <= '$now' ORDER BY date_field DESC LIMIT 1 OFFSET 1";
Add an ORDER BY statement to the query. The following will order the rows by their date, with the latest at the top and oldest at the bottom.
SELECT `id`, `date` FROM `table` ORDER BY `date` DESC LIMIT 1;
I'm looking for a best practice advice how to speed up queries and at the same time to minimize the overhead needed to invoke date/mktime functions. To trivialize the problem I'm dealing with the following table layout:
CREATE TABLE my_table(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
important_data INTEGER,
date INTEGER);
The user can choose to show 1) all entries between two dates:
SELECT * FROM my_table
WHERE date >= ? AND date <= ?
ORDER BY date DESC;
Output:
10-21-2009 12:12:12, 10002
10-21-2009 14:12:12, 15002
10-22-2009 14:05:01, 20030
10-23-2009 15:23:35, 300
....
I don't think there is much to improve in this case.
2) Summarize/group the output by day, week, month, year:
SELECT COUNT(*) AS count, SUM(important_data) AS important_data
FROM my_table
WHERE date >= ? AND date <= ?
ORDER BY date DESC;
Example output by month:
10-2009, 100002
11-2009, 200030
12-2009, 3000
01-2010, 0 /* <- very important to show empty dates, with no entries in the table! */
....
To accomplish option 2) I'm currently running a very costly for-loop with mktime/date like the following:
for(...){ /* example for group by day */
$span_from = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i, date("Y", $time_min));
$span_to = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i+1, date("Y", $time_min));
$query = "..";
$output = date("m-d-y", ..);
}
What are my ideas so far? Add additional/ redundant columns (INTEGER) for day (20091212), month (200912), week (200942) and year (2009). This way I can get rid of all the unnecessary queries in the for loop. However I'm still facing the problem to very fastly calculate all dates that doesn't have any equivalent in database. One way to simply move the problem could be to let MySQL do the job and simply use one big query (calculate all the dates/use MySQL date functions) with a left join (the data). Would it be wise to let MySQL take the extra load? Anyway I'm reluctant to use all these mktime/date in the for loop. Since I have complete control over the table layout and code even suggestions with major changes are welcome!
Update
Thanks to Greg I came up with the following SQL query. However it still bugs me to use 50 lines of sql statements - build up with php - that maybe could be done faster and more elegantly otherwise:
SELECT * FROM (
SELECT DATE_ADD('2009-01-30', INTERVAL 0 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 1 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 2 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 3 DAY) AS day UNION ALL
......
SELECT DATE_ADD('2009-01-30', INTERVAL 50 DAY) AS day ) AS dates
LEFT JOIN (
SELECT DATE_FORMAT(date, '%Y-%m-%d') AS date, SUM(data) AS data
FROM test
GROUP BY date
) AS results
ON DATE_FORMAT(dates.day, '%Y-%m-%d') = results.date;
You definitely shouldn't be doing a query inside a loop.
You can group like this:
SELECT COUNT(*) AS count, SUM(important_data) AS important_data, DATE_FORMAT('%Y-%m', date) AS month
FROM my_table
WHERE date BETWEEN ? AND ? -- This should be the min and max of the whole range
GROUP BY DATE_FORMAT('%Y-%m', date)
ORDER BY date DESC;
Then pull these into an array keyed by date and loop over your data range as you are doing (that loop should be pretty light on CPU).
Another idea is not to use string inside the query. Transform the string parameter to datetime, on mysql.
STR_TO_DATE(str,format)
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html