Select rows from yesterday's date - mysql

I have a query function that selects all rows from the previous days. However, I need it to only select the rows with yesterdays date but am unsure how to include just the previous day.
My current query is:
SELECT pdate FROM table 1
WHERE pdate < Date(NOW()) + INTERVAL 1 DAY

I would imagine it would look something like this, which has the advantage of using indexes (if you have them implemented)
SELECT pdate FROM table 1
WHERE pdate >= Date(NOW()) - INTERVAL 1 DAY
AND pdate < Date(NOW())

You can use the DATE_SUB() function to get yesterday's date, and then use a WHERE clause condition to look for just that date, like this:
SELECT *
FROM myTable
WHERE DATE(pDate) = DATE_SUB(pDate, INTERVAL 1 DAY);
Here is a list of MySQL's Date and Time Functions which may help you.
NOTE: This will work, but because you are using a function on the pDate column in the where clause this will not be able to take advantage of any indexes you have (see comments below). Brian Driscoll has given an answer that will work better. I am choosing to leave this answer because while it is less efficient, I believe it is more readable as the where clause is very explicit in what it is checking and is slightly more readable. Whether or not the trade off is worth it here is up to the developer.

Related

SQL date_sub vs datediff performance in looking over a date window

I'm trying to look at the number of active users of a product (toy example) over the last 30 days.
I'm considering two approaches.
One, date_sub is used to find the date 29 days before (the interval is 30 days inclusive of the start date) an end date. The where window is then defined by that earlier date and the end date.
That is this example:
SELECT
activity_date AS day,
COUNT(DISTINCT user_id) AS active_users
FROM Activity
WHERE
activity_date >= DATE_SUB("2019-07-27", INTERVAL 29 DAY)
AND
activity_date >= "2019-07-27"
A second approach is to calculate the datediff from a start date, then restrict the where clause to the previous time period.
SELECT
activity_date as day,
COUNT(DISTINCT user_id) AS active_users
FROM Activity
WHERE
datediff('2019-07-27', activity_date) < 30
AND
activity_date <= '2019-07-27'
I have no insight into which is the better option. I'd love for others to weigh in.
Use the first option:
activity_date
BETWEEN DATE_SUB(DATE("2019-07-27"), INTERVAL 29 DAY)
AND DATE("2019-07-27")
This compares the stored value directly to date litterals. Such an expression can take advantage of an index on the date column.
In, constrast the second expression applies date function datediff() to the date column. This makes the expression non-SARGable, meaning that it will not benefit an index:
datediff('2019-07-27', activity_date) < 30
and activity_date <= '2019-07-27'
Note that the first expression could be simply phrased:
activity_date >= '2019-07-27' - interval 29 day
and activity_date <= '2019-07-27'
I am unsure whether the second comparison should be >= rather than >. A reason why it would make sense is that activitydate has no time component. But I would recomment using <, because it works for both cases; if you want data up until '2019-07-27' included, you can do:
activity_date >= '2019-07-27' - interval 29 day
and activity_date < '2019-07-28'
I would definitely use the first query, if you have an index on the activity_date column.
When you do DATE_SUB() or DATE() on constant values, MySQL only needs to do that calculation once before it begins examining rows. The result of the expression is a constant.
Comparing an indexed column BETWEEN the two constant values, then it can use that index to locate the matching rows efficiently, using a range search.
Whereas if you put your column inside the call to DATEDIFF(), it has to re-calculate the result on every row examined, and it can't use the index. It will be forced to examine every row in the table. This is called a table-scan.
You can use EXPLAIN to confirm this. The first query will show type: range but the second query will show type: ALL, and the row column of the EXPLAIN will show an estimate roughly equal to the size of the table.
FWIW, this is generally true: any expression where you put a column inside a function call spoils any benefit of an index on that column. Indexes work because they're stored in sorted order, but MySQL can't use an index on a column inside an expression or function, because it doesn't do any analysis to determine if the result of the expression has the same sort order as the column itself.

MySQL group by TimeStamp

I am writing a Python code where I need to use MySQLdb to retrieve data from a MySQL database. A part of the original database looks like this:
I used this command
SELECT TimeStamp,Pac
FROM SolarData
WHERE DATE(`TimeStamp`) = CURDATE()
GROUP BY HOUR(TimeStamp);
to group the data by hour, but the result is not what i expected:
The Pac number shown for every hour is the same number as the first record of each hour. It's not an accumulated number for the whole hour. What I need is an accumulated number of the whole hour.
That's because MySQL is like your alcoholic uncle when you don't use GROUP BY by the ANSI standard. You probably want:
SELECT HOUR(TimeStamp) AS Hour,
SUM(Pac) AS Pac
FROM SolarData
WHERE `TimeStamp` >= CURDATE()
AND `TimeStamp` < CURDATE() + INTERVAL 1 DAY
GROUP BY HOUR(TimeStamp);
It would be helpful to see the desired result you're looking for. Until then, the above query is just a guess based on group the data by hour. For future reference, use SQL Fiddle to post your table structure/data.
"How do I decorate the code so that the hour format can have the date on it as well like this 2014-01-14 07:00"
All of Hour belong to today (CURDATE()), and second part is always ':00', so following query might help you. Could try this?
SELECT CONCAT(CURDATE(), ' ', Hour, ':00'), Pac
FROM (
SELECT HOUR(TimeStamp) AS Hour,
SUM(Pac) AS Pac
FROM SolarData
WHERE DATE(`TimeStamp`) = CURDATE()
GROUP BY HOUR(TimeStamp)
) x;

Select current months records mysql from timestamp column

I have a mysql DB that has a TIMESTAMP field titled date. How can I select all fields where the month is the current month?
Thanks in advance!
UPDATE
A much better index-friendly way to query your data for a range of dates
SELECT id, FROM_UNIXTIME(timestampfield) timestamp
FROM table1
WHERE timestampfield >= UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY - INTERVAL 1 MONTH)
AND timestampfield < UNIX_TIMESTAMP(LAST_DAY(CURDATE()) + INTERVAL 1 DAY);
Note: You don't apply any function to your column data, but rather do all necessary calculations on the right side of the conditions (which are constants and are evaluated only once post-execution). This way you allow MySQL to benefit from index(es) that you might have on the timestampfield column.
Original answer:
SELECT id, FROM_UNIXTIME(timestampfield) timestamp
FROM table1
WHERE MONTH(FROM_UNIXTIME(timestampfield)) = MONTH(CURDATE())
AND YEAR(FROM_UNIXTIME(timestampfield)) = YEAR(CURDATE())
Note: Although this query produces the correct results it effectively invalidates the proper usage of the index(es) that you might have on the timestampfield column (meaning MySQL will be forced to perform a fullscan)
Here is SQLFiddle demo
Use this query may this help you,
Query = "SELECT * FROM <table_name> WHERE MONTH(date_entered) = MONTH(CURDATE())";
In my opinion, the following is more readable than the accepted answer...
SELECT id, FROM_UNIXTIME(timestampfield) timestamp
FROM table1
WHERE timestampfield >= DATE_FORMAT(NOW(), '%Y-%m-01')
Note: This would select any records from the next month as well. That usually doesn't matter, because none have been created.
If you want indexes to be used, don't apply any function to the column:
SELECT *
FROM tableX
WHERE `date` >= UNIX_TIMESTAMP((LAST_DAY(NOW())+INTERVAL 1 DAY)-INTERVAL 1 MONTH)
AND `date` < UNIX_TIMESTAMP(LAST_DAY(NOW())+INTERVAL 1 DAY) ;
The functions used can be found in MySQL docs: Date and Time functions
try this
SELECT * FROM table WHERE month(data) = EXTRACT(month FROM (NOW()))
SELECT 'data of your choice '
FROM 'your table'
WHERE
MONTH'datecolumn'=MONTH(CURRENT_DATE )
replace text in ' ' with appropriate from your database
SELECT [columns]
FROM [the_table]
WHERE MONTH([date_column]) = MONTH(CURDATE())
Replace the text between [] (including the []) with your data.
The query below can benefit from the index and no functions applied to the timestamp field for where clause evaluation.
SELECT *
FROM TableName
WHERE TimestampField >=
(CURDATE() - INTERVAL (DAY(CURDATE())-1) DAY)
AND TimestampField <
LAST_DAY(CURDATE()) + INTERVAL 1 DAY;
If your timestamp field is time part is truncated, go for this one,
SELECT *
FROM TableName
WHERE TimestampField BETWEEN
(CURDATE() - INTERVAL (DAY(CURDATE())-1) DAY)
AND
LAST_DAY(CURDATE());
As of 2020, you can use BETWEEN to handle the query from the very beginning.
SELECT *
FROM [TABLE]
WHERE [DATE_FIELD]
BETWEEN
CAST('2020-30-01' AS DATE) AND CAST('2020-10-31' AS DATE);
I know is not the most "automatic" way, but from a SQL perspective it is very friendly and straightforward.
Source
https://www.techonthenet.com/mysql/between.php
Try this one it will work better because of the range. You don't need to calculate month and year for every row. It will slow the process. User range for better performance.
SELECT * FROM table WHERE columnName between DATE_FORMAT(current_date() ,'%Y-%m-01') and current_date();
SELECT
*
FROM
tableName
WHERE
EXTRACT(YEAR_MONTH FROM columnName) = EXTRACT(YEAR_MONTH FROM CURDATE())
I think in MySQL here is the simplest method which i have tried and works well, you want to select rows where timestampfield is in this month.
SELECT * FROM your_table
WHERE MONTH(timestampfield)=MONTH(CURRENT_DATE()) AND
YEAR(timestampfield)=YEAR(CURRENT_DATE());
the above will return all records that the timestampfield is this month in MySQL

Calculate difference between dates

The title might be a bit misleading, but what I want is:
SELECT * FROM table ORDER BY pid ASC
And in one of the columns I have a DATE(). I want to compare the current date (not time) and return how many days are left till that date. Let's say the date is 2013-04-20 and today's date is 2013-04-16 I don't want to get any data if it's < current date. If it is I want it returned in days.
I've been looking around here and I've found no way to do it, and I can't for the love of me figure it out.
If you're looking for the difference between two date you can use the GETDATE function in MS SQL
SELECT DATEDIFF(DD, DateOne, DateTwo) FROM TABLE
This will return the difference in number of days between the two dates.
If you only want rows where the date field is less than or equal to today's date you can use:
SELECT DATEDIFF(DD, DateField, GETDATE())
FROM TableName
WHERE DateField <= GETDATE()
If you're using MySQL you can use DATEDIFF()
SELECT
DATEDIFF(NOW(), date_column) AS days_diff
FROM
tablename
Get the difference between two dates (ANSI SQL)
select the_date_column - current_date as days_left
from the_table
where the_date_column - current_date <= 4;
SQLFiddle: http://sqlfiddle.com/#!12/3148d/1

Is there anyway to do math on a MySQL query?

I have two fields, one with the purchase date and one with the lifespan of an item. I am wondering if there is any way to determine if the current date is past the lifespan. So, pretty much if MySQL could test if current_date is > purchase_date + lifespan.
The purchase date is a date formated yyyy-mm-dd and lifespan is an integer of months. Is there any way to perform this calculation?
You might try:
SELECT * FROM table WHERE NOW() > (purchase_date + INTERVAL lifespan MONTH)
But you might use
SELECT * FROM table WHERE NOW() > date_add(purchase_date, INTERVAL lifespan MONTH)
Or DATEDIFF
SELECT * FROM table WHERE DATEDIFF(NOW(), purchase_date) / 30 < lifespan
How about using DATEDIFF?
Your query would be something along these lines:
SELECT * FROM table WHERE DATEDIFF(NOW(), purchase_date) < lifespan
Forgive me if my syntax is a little off, I don't have an SQL instance to test on right now
Yes it is possible, using the MySQL date and time functions.