Mysql query list results matching each date - mysql

Not sure how this would work. I have a between query, but how would I run a query to list results that match each and every day. Example, enterys that exists on 2011-06-17, 2011-06-18, 2011-06-19 and 2011-06-20
SELECT lookup, `loc`, `octect1` ,`octect2` ,`octect3` ,`octect4`, date, time, count(`lookup`) as count FROM index
WHERE date between '2011-06-17' AND '2011-06-20'
GROUP BY lookup
ORDER BY count DESC
Thanks

Instead of BETWEEN, use comparison operators:
SELECT lookup, `loc`, `octect1` ,`octect2` ,`octect3` ,`octect4`,
date, time, count(`lookup`) as count
FROM index
WHERE date > '2011-06-17' AND date < '2011-06-20'
GROUP BY lookup
ORDER BY count DESC

Related

How to get the number of registers by month and date

I have rows of user data. I store the createDate, which is the timestamp in milliseconds when the user registered. I want to get the total number of registrations per month. When I try to do that, I don't get any rows returned. Here's the query I'm using
SELECT COUNT(*) FROM users WHERE YEAR(createDate) = 2023 GROUP BY MONTH(createDate)
createDate is BIGINT and is the date in milliseconds
I guess your createDate column is defined as TIMESTAMP(3), to get millisecond resolution. LAST_DAY() comes in handy here.
Try this:
SELECT COUNT(*), LAST_DAY(createDate) month_ending
FROM users
WHERE createDate >= '2023-01-01'
AND createDate < '2024-01-01'
GROUP BY LAST_DAY(createDate)
The date range test I use for getting the dates in a single year is sargable. That is, it can be accelerated by an index on createDate, where YEAR(createDate) cannot be.
This approach generates a useful result set if you run it on a multi-year date range.
But, if your result set is empty (has no rows), the result set from this query will be too. That might mean:
your table has no dates in that range, or
your createDate data type is something other than TIMESTAMP or DATETIME. (You didn't show us the table definition.)
It sounds like you need to convert to/from unix time:
SELECT COUNT(*), LAST_DAY(FROM_UNIXTIME(createDate/1000)) month_ending
FROM users
WHERE createDate >= UNIX_TIMESTAMP('2023-01-01') * 1000
AND createDate < UNIX_TIMESTAMP('2024-01-01') * 1000
GROUP BY month_ending

Comparing performance of query for year in date

How would the following three queries compare in terms of performance? I'm trying to get all records with year=2017:
Using EXTRACT:
SELECT count(*), completed_by_id FROM table
WHERE EXTRACT(YEAR FROM completed_on)=2017
GROUP BY completed_by_id
# Took 11.8s
Using YEAR:
SELECT count(*), completed_by_id FROM table
WHERE YEAR(completed_on)=2017
GROUP BY completed_by_id
# Took 5.15s
Using LIKE 'YEAR%'
SELECT count(*), completed_by_id FROM table
WHERE completed_on LIKE '2017%'
GROUP BY completed_by_id
# Took 6.61s
Note: In my own testing I found YEAR() to be the fastest, LIKE to be the second fastest, and EXTRACT() to be the slowest.
There are about 5M rows in the table and completed_on is DATETIME field that has been indexed.
You haven't described your table or indexes so all advice about query performance is guesswork.
If your completed_on column is a DATETIME, DATE, or TIMESTAMP type and it is indexed, this query will radically outperform all the ones you have shown, and maintain its performance as your table grows.
SELECT count(*), completed_by_id
FROM table
WHERE completed_on >= '2017-01-01'
AND completed_on < '2017-01-01' + INTERVAL 1 YEAR
GROUP BY completed_by_id
Why? It can do a range scan on the index rather than a nonsargable function call on each row's value.
Notice the use of >= at the beginning of the date range and < at the end. We want to include all rows from the first moment of new years day 2017, up until but not including the first moment of new years day 2018. BETWEEN can't do this, because it uses <= rather than < at the end of its range.
If an index is in place, both BETWEEN and the syntax I have shown use a range scan, and perform about the same.
For best results speeding up this query use a compound index on (completed_on, completed_by_id).
If you are storing completed_on as DATE or DATETIME you can use:
SELECT count(*) as cnt, LEFT(completed_on, 4) AS year
FROM table
GROUP BY year
HAVING year=2017

MYSQL inappropriate query

I have following two queries and their out comes are different but what I want is as following:
I have two tables:
Subject:
-subject_id (Primary key)
-about
-details
feedback:
-id (Primary Key)
-subject_id (Foreign key)
-rating
-DateAndTime
Following are the queries and their result in words:
SELECT distinct about, details, subject.subject_id, round(AVG(rating),2) as Rating,
Max(DATE_FORMAT( DateAndTime, '%d-%m-%Y' )) as Date,
Max(TIME_FORMAT( DateAndTime, '%h:%i:%s' )) as Time
FROM `subject` , `feedback`
WHERE subject.Subject_ID = feedback.Subject_ID
GROUP BY about,details,subject_id
ORDER BY DateAndTime DESC
Here in this query the output is unique about,details,subject_id column and average rating. But Problem is with date and time. I want the last date and time entered for that result and result also contains that but it isn't in ordered manner.
above query's image
When i perform this query it gives perfect order but the rating gets revised
SELECT distinct about, details, subject.subject_id, round(AVG(rating),2) as Rating,
Max(DATE_FORMAT( DateAndTime, '%d-%m-%Y' )) as Date,
Max(TIME_FORMAT( DateAndTime, '%h:%i:%s' )) as Time
FROM `subject` , `feedback`
WHERE subject.Subject_ID = feedback.Subject_ID
GROUP BY about,details,subject_id,dateandtime
ORDER BY DateAndTime,Time DESC
The difference is just in group by clause.
So anyone could help me please.
When you put the day first in the date format, MAX() will select the date with the highest day number, which isn't necessarily the most recent date. For instance, 26-10-2016 is higher than 21-11-2017 because 26 is higher than 21. To order by a formatted date, it has to be in %Y-%m-%d format.
And when you select the maximum time after formatting, you're getting the highest time ignoring the date entirely.
Instead of applying MAX() to the result of DATE_FORMAT, get the maximum DateAndTime and format that as desired:
DATE_FORMAT(MAX(DateAndTime, '%d-%m=%Y')) AS Date,
DATE_FORMAT(MAX(DateAndTime, '%h:%i:%s')) AS Time
To order the results by the displayed date and time, use:
ORDER BY STR_TO_DATE('%d-%m-%Y %h:%i:%s', CONCAT(Date, ' ', Time)) DESC
And you shouldn't have DateAndTime in the GROUP BY, because then you'll get a separate group for each time. You need to combine all the times into a single group so you can then get the last value for it with MAX(DateAndTime).

MySQL to return only last date / time record

i have a table that has a serial number, date and time when that serial number was modified. i would like to retrieve the latest time and date when that particular serial number was modified. any suggestions? the dates and times are on different columns.
thanks
Assuming the data and time columns are of types that MySQL knows how to sort correctly (i.e. DATE and TIME types), this should work:
SELECT * FROM table_name
ORDER BY date_col DESC, time_col DESC
LIMIT 1
Depends on how one can find the most recent record – can there be multiple rows with the same date and time ?
Is the serial number monotonically increasing or decreasing ?
Try using ORDER BY (DESC sorts from newest to oldest) and LIMIT to get what you want, e.g.
SELECT * FROM `table` ORDER BY `date` DESC, `time`, `serial` DESC LIMIT 1

Is it possible to group rows by a day stored within a timestamp?

I'm not sure if this is even within the scope of MySQL to be honest or if some php is necessary here to parse the data. But if it is... some kind of stored procedure is likely necessary.
I have a table that stores rows with a timestamp and an amount.
My query is dynamic and will be searching based on a user-provided date range. I would like to retrieve the SUM() of the amounts for each day in a table that are between the date range. including a 0 if there are no entries for a given day
Something to the effect of...
SELECT
CASE
WHEN //there are entries present at a given date
THEN SUM(amount)
ELSE 0
END AS amountTotal,
//somehow select the day
FROM thisTableName T
WHERE T.timeStamp BETWEEN '$start' AND '$end'
GROUP BY //however I select the day
This is a two parter...
is there a way to select a section of a returned column? Like some kind of regex within mysql?
Is there a way to return the 0's for dates with no rows?
select * from thisTableName group by date(created_at);
In your case, it would be more like
SELECT id, count(id) as amountTotal
FROM thisTableName
WHERE timeStamp BETWEEN '$start' AND '$end'
GROUP BY DATE(timeStamp);
Your question is a duplicate so far: link.