Select Range of Items by Year and Month - mysql

I'm attempting to create a select statement which gets items by year and month.
This is what I have so far:
SELECT * FROM sales WHERE YEAR(Date) = 2013 AND MONTH(?) = 'June'
I can't merely select date ranges because different months have different number days. It would be ideal to select months by their number (ie, January being 1) or a similar approach.
How is this worked out in a mysql statement?
The fields are datetime fields such as 2012-12-01 00:00:00

Have a look at the performance and write your condition as
SELECT * FROM sales
WHERE
Date >= '2013-06-01 00:00:00'
AND
Date < '2013-07-01 00:00:00'
for the example month: June of 2013
so MySQL can use an index on the column date. You will get exactly all rows with a date in the June of 2013, even those in the first second, but not those in the first second of the July of 2013.
You see, that you don't need to know the number of days of the particular month, because you will ever use the first of both months.
You could use a bit of date calculation too:
SELECT * FROM sales
WHERE
Date >= '2013-06-01 00:00:00'
AND
Date < '2013-06-01 00:00:00' + INTERVAL 1 MONTH
so you need only to know the start and the length of the interval.
Note
The most important part of my answer is to use the column Date without using a function on this column, so MySQL can use an index.

Related

How do I query in mysql to select beetween 4 PM and 10 PM for a whole month

So I have a problem to select data from my database. I want to select data with recorded time between 4 PM and 10 PM for a whole month. If it's isn't possible should I query per day for a whole month?
Assuming mydt column is DATETIME or TIMESTAMP datatype,
we could do something like this:
FROM t
WHERE t.mydt >= '2019-09-01'
AND t.mydt < '2019-09-01' + INTERVAL 1 MONTH
AND DATE_FORMAT(t.mydt,'%H') >= '16'
AND DATE_FORMAT(t.mydt,'%H') < '22'
The first two conditions restrict values to the month of September 2019.
The last two conditions restrict the "hour" portion of the datetime, time values from 16:00:00 thru 21:59:99
If we also want to include 22:00:00, we can use '%T' as format model in DATE_FORMAT and do a less than or equal to comparison
AND DATE_FORMAT(t.mydt,'%T') >= '16:00:00'
AND DATE_FORMAT(t.mydt,'%T') <= '22:00:00'

MySQL select records between day of the year and year

I have a table where I insert the year, month number, week number of the year, and day number of the year with each record.
I'm using those fields to filter records instead of full date because I have millions of records, and I want to increase the performance by comparing integers instead of dates.
I was able to select records between dates based the day number and year. The query works well if the years are the same, but once I change the year the query doesn't work because I'm using AND.
Table looks like this:
ID
Day
Week
Month
Year
Full Date
Here is the working query
SELECT COUNT(id) AS records_count
FROM table1
WHERE table1.day >= 176
AND table1.day <= 275
AND table1.year <= 2015
AND table1.year >= 2015
And this is the query that I need to adjust
SELECT COUNT(id) AS records_count
FROM table1
WHERE table1.day >= 275
AND table1.day <= 176
AND table1.year <= 2014
AND table1.year >= 2015
Your method of storing the dates is exactly wrong for what you want to do. The general form would be:
where (year = 2014 and day >= 275 or year > 2014) and
(year = 2015 and day <= 176 or year < 2015)
This will work for any pair of years, not just those that are one year apart.
Now, if you stored the dates normally, then you would simply do:
where date >= makedate(2014, 275) and date <= makedate(2015, 176)
What is really, really nice about this structure is that MySQL can use an index on date. That isn't possible with your query.
In general, a micro-optimization such as using integers instead of some other data type is not worth the effort in relational databases. Usually, the cost of reading the data is much more expensive than processing within a row. And, in fact, this example is a great example of it. Why try to increase the speed of comparisons when you can remove the need for them entirely using an index?
SELECT COUNT(id) AS records_count
FROM table1
WHERE (year = 2014 and day >= 275)
OR (year = 2015 and day <= 176)
And as baao commented - an indexed date column is super fast and easier to query.
Generalized solution (can be from year 2000 to 2020 for example)
SELECT COUNT(id) AS cnt
FROM tbl
WHERE ((year > under_min_year and year < above_max_year)
and ((year <> min_year and year <> max_year)
or (year = min_year and day > 265)
or (year = max_year and day < 300)))
The problem is that you want to count the records that have the year smaller or equal than 2014 AND the same year bigger or equal than 2015. There's no number smaller or equal than 2014 and in the same time bigger or equal than 2015.

Need to find duplicates with multiple criteria and then comparing dates between duplicates

I am writing annual membership registrations to a single db table. I need to keep track of when renewals have occurred in less than 11 months from their last renewal.
I look for the duplicate rows based on multiple criteria. I currently have this working with out the 11 month criteria, although it's slow. Here's what I currently use.
SELECT y_reg.* FROM y_reg WHERE (((y_reg.season) In (SELECT season FROM y_reg As Tmp
GROUP BY season, Father_Last_Name, Father_First_Name
HAVING Count(*)>1
AND Father_Last_Name = y_reg.Father_Last_Name
AND Father_First_Name = y_reg.Father_First_Name)))
ORDER BY y_reg.season, y_reg.Father_Last_Name, y_reg.Father_First_Name
I have a field Date which is the date of the renewal that I need to evaluate. I'd like to add something like "AND Date - Date < 335"
335 is the number of days and is about 1 month short of a year. But I just keep getting syntax error because I clearly don't know what I'm doing.
Date arithmetic works quite well in MySQL; you just need the knack.
You can say things like
AND later.Date >= earlier.Date
AND later.Date < earlier.Date + INTERVAL 11 MONTH
That particular pair of comparisons comes up true if the later date occurs in the time range between the earlier date and 11 months later.
In general you can say stuff like this to do date arithmetic.
datestamp + INTERVAL 1 HOUR
datestamp - INTERVAL 5 MINUTE
datestamp + 1 MONTH - 3 WEEK
datestamp - INTERVAL 3 QUARTER (calendar quarters)
LAST_DAY(datestamp) + INTERVAL 1 DAY - INTERVAL 1 MONTH
The last item is the first day of the month containing the datestamp. This whole date thing works quite well.
I think you should consider a so-called self-join query to get your duplicate-except-for-date results. Try something like this.
SELECT a.*
FROM y_reg a
JOIN y_reg b ON a.Father_Last_Name = b.Father_Last_Name
AND a.Father_First_Name = b.Father_First_Name
AND b.Date < a.Date - 11 MONTH
AND b.Date >= a.Date - 12 MONTH

How to check if date is in range regardless of the year

I'm wondering what would be the easiest way in MySQL to check if given date is in range regardless of the year.
In database table I have two DATE fields: start and finish stored in YYYY-mm-dd
if start = 2013-11-01 and finish = 2014-03-01 anything between 1st of November and 1st of March of any year should be accepted.
Valid dates:
2020-01-01 1980-02-28
Invalid dates:
2013-10-30 1968-07-30
There are almost certainly cleaner ways of doing it, however this should work:
((DAYOFYEAR(finish_date) > DAYOFYEAR(start_date)
AND (DAYOFYEAR(#date) >= DAYOFYEAR(start_date)
AND DAYOFYEAR(#date) <= DAYOFYEAR(finish_date)))
OR (DAYOFYEAR(finish_date) <= DAYOFYEAR(start_date)
AND (DAYOFYEAR(#date) >= DAYOFYEAR(start_date)
OR DAYOFYEAR(#date) <= DAYOFYEAR(finish_date))))
For a start date in Oct 2012 and end date in Nov 2020 this will return all dates in the Oct-Nov range. If in fact would want it to return all Dates when the range is greater than a year (and hence covers all dates of the year) you could add:
OR DATEDIFF(Day, start_date, finish_date) > 356
before the final bracket.
use DAYOFYEAR:
When the Start Date is earlier in the year than the Finished Date:
the tested Date should lye between Start Date and Finish Date (or on Start or Finish)
When the Finished Date is earlier in the year than the Start Date:
the tested Date should lye outside the Start Date and Finish Date (or on Start or Finish)
You can use some date extract function and then check your condition..
for example.
SELECT EXTRACT(MONTH FROM TIMESTAMP '2013-11-01 20:38:40');
this will give ouput start month as 11
SELECT EXTRACT(MONTH FROM TIMESTAMP '2014-03-01 20:38:40');
this will give ouput end month as 3
now you can check the condition from above two result..
SELECT * FROM tableWithDates t WHERE month(t.start) >= 11 AND month(t.finish) < 3
if you want the first of march it will go like this:
SELECT * FROM tableWithDates t WHERE month(t.start) >= 11 AND (month(t.finish) < 3 OR month(finish) <= 3 AND day(finish)<=1)
Depending on the size of the data you will run this at. You can get into performance problems, as MySQL can't use indexes of calculated columns.
If you run into this i suggest spitting the month AND/OR day into separate columns.
Edit:
Given an one parameter input as '2008-02-29'
SELECT * FROM tableWithDates t
WHERE
month(t.start) >= month('2008-02-29') AND day(t.start) >= day('2008-02-29')
AND month(t.finish) <= month('2008-02-29') AND day(t.finish) <= day('2008-02-29')

mysql get current date and row date

Is it possible to do sql query on what day is today and get the row of today for date column?
So let say today is july 25th, i have database table sales, column name date, date = sales transaction date in timestamp.
i need all row that the sales date is same with current date and also is it possible set value as gmt+5?
This will get you all the rows for today's date:
SELECT * FROM sales
WHERE DATE(NOW()) = DATE(DATE_ADD(sales_transaction, INTERVAL 5 HOUR))
ORDER BY sales_transaction
As for GMT +5, Do you mean all rows with a sales date +5 hours or today +5 hours?
EDIT: Updated to add 5 hours to sales date. For a column called date, I would use the back-ticks to indicate it's a column name. e.g. SELECT `date`` FROM sales
I can't figure out how to work the back-ticks on the date field. But you should get the idea. Wrap your column names with `
Give some time and Check out Date Time Function of mySQL
SELECT * FROM tablename WHERE salesdate = '1998-1-1';
If your date is stored in GMT timezone
Select *
FROM tablename
WHERE DATE_ADD(NOW(), INTERVAL 5 HOUR) = salesdate
SELECT * FROM `sales` WHERE DAYOFMONTH(FROM_UNIXTIME(date)) = DAYOFMONTH(DATE(now()))
seems working.
Thank you for all of your replies.