Let's guess we've got the following table:
- id (int)
- active (int)
- active_from (datetime) (NULL)
- active_until (datetime) (NULL)
Now, what I want to get is all the active records. An active record implies:
- active = 1
- active_from <= current_date (IF IT'S NOT NULL)
- active_until >= current_date (IF IT'S NOT NULL)
I'm looking for a query that applies these 3 requirements in one single query. I'm currently using:
SELECT * FROM product WHERE active = 1 AND active_from <= NOW() AND active_until >= NOW();
I will only get the behavior I want with rows that don't have NULL active_from or active_until.
Note: I know it would be more appropiate to compare the current date after storing it in a variable (posing it this way because I'm filling it with PHP parameters).
Thank you in advance.
SELECT * FROM YourTableName
WHERE active = 1
AND (active_from < CURDATE()
OR active_from IS NULL)
AND (active_until > CURDATE()
OR active_until IS NULL);
Use ifnull in your query (encase active_from and active_until in it):
https://dev.mysql.com/doc/refman/5.7/en/control-flow-functions.html#function_ifnull
So, basically, if the value is null, use another date instead. Which date is up to you and the specific business logic you need (ex: 2100-01-01 or 1900-01-01 etc.)
SELECT * FROM product
WHERE active = 1
AND (active_from < CURDATE()
AND active_from IS NOT NULL)
AND (active_until > CURDATE()
AND active_until IS NOT NULL)
Related
Consider I have the following table and current date is 2022-09-01:
Requirement: I want to get all users that have no event_name like cbt care in the past 14 days and onwards into the future.
I have this query:
SELECT * FROM test_table
WHERE event_name LIKE "%cbt care%"
AND start_date <= DATE_SUB(NOW(), INTERVAL 14 DAY)
;
Which returns:
The issue is that user_id = x does have a cbt care event in 2022-09-10 which is 9 days ahead of current date (2022-09-01).
How to return only users satisfy requirement posted above?
SELECT user_id,
COUNT(CASE WHEN event_name LIKE '%cbt care%' AND start_date
> CURDATE() - INTERVAL 14 day THEN 1 END) AS count_recent
FROM test_table
GROUP BY user_id
HAVING count_recent = 0;
https://www.db-fiddle.com/f/64j7L1VZsVdLYqmcQ2NrvV/0
The CASE expression returns 1 for each row with the conditions you described (a specific event name and a start date after the date 14 days ago, which includes all of the future dates too). For rows that don't match that condition, the CASE returns NULL. There's an implicit ELSE NULL in any CASE expression.
COUNT(<expr>), like many set functions, ignores NULLs. It will only count the occurrences of non-NULL values. So if the count returns 0, then the CASE returned only NULLs, which means there are no recent or future 'cbt care' events for that user.
select id
,user_id
,event_name
,start_date
from (
select *
,count(case when abs(datediff(curdate(),start_date)) <= 14 and event_name like "%cbt care%" then 1 end) over (partition by user_id) as cw
from t
) t
where cw = 0
id
user_id
event_name
start_date
0
a
cbt care
2022-06-01 20:00:00
Fiddle
i have records in my database like this
*just example
id
Name
created_at
1
Jono
2020-03-21 12:20:00
2
Abi
2020-03-25 12:20:00
3
Iko
2020-03-30 12:20:00
then i have simple query like this
SELECT * FROM `transaksi` WHERE `created_at` >= '2020-03-21' AND `created_at` <= '2020-03-30'
but that query only show id no 1 and 2 which is the date is < 2020-03-30
so my question is
why the third data which is still in range is not showing?
i have try something like this too
SELECT * FROM `transaksi` WHERE `created_at` >= DATE('2020-03-21') AND `created_at` <= DATE('2020-03-30')
but still have same issue
any sugestion?
thanks
This is the logical query you want here:
SELECT *
FROM transaksi
WHERE created_at >= '2020-03-21' AND created_at < '2020-04-01';
To explain what the above is actually saying, let's rewrite it using timestamp literals, with full H:M:S components:
SELECT *
FROM transaksi
WHERE created_at >= '2020-03-21 00:00:00' AND created_at < '2020-04-01 00:00:00';
Both of these queries will retain any record having a created date on or after midnight of 21-March-2020 and strictly before midnight of 1st-April-2020. The right side condition then includes the entire day of 31-March-2020.
You have to apply mysql DATE() function on created_at column to get date only without time.
SELECT *
FROM `transaksi`
WHERE DATE(`created_at`) >= '2020-03-21'
AND DATE(`created_at`) <= '2020-03-30'
SQL DEMO
I have 3 Queries
SELECT * FROM `admin_sprints`
where CURDATE() < `sprint_start_date` and
CURDATE() <`sprint_end_date` - retuen type as future
SELECT * FROM `admin_sprints`
where CURDATE() > `sprint_start_date` and
CURDATE() >`sprint_end_date` - retuen type as past
SELECT * FROM `admin_sprints`
where CURDATE() between `sprint_start_date` and
`sprint_end_date` - retuen type as current
i tried to combine this to single queries
So i tried
SELECT
*
FROM
admin_sprints
ORDER BY (CASE
WHEN sprint_start_date` and CURDATE() <`sprint_end_date` THEN future
ELSE admin_sprints` where CURDATE() > `sprint_start_date` and CURDATE() >`sprint_end_date then over
ELSE current
END);
admin_sprints
---------------|------------|-----------------|-----------------------
sprint_id |sprint_name |sprint_start_date| sprint_end_date |
1 Sprint1 2018-11-01 2018-11-13
2 sprint2 2018-11-14 2018-11-23
3 sprint 3 2018-11-24 2018-11-130
expected output
sprint_id sprint_name type
1 Sprint1 over
2 Sprint2 Active
3 Sprint3 future
I don't know method is correct or not.Bad luck it's not working.Any help would be appreciated
You need to use the CASE..WHEN statements in your SELECT clause, to determine the type accordingly. Try:
SELECT
*,
CASE WHEN sprint_start_date < CURDATE() AND
sprint_end_date < CURDATE()
THEN 'over'
WHEN CURDATE() BETWEEN sprint_start_date AND
sprint_end_date
THEN 'active'
ELSE 'future'
END AS type
FROM
admin_sprints
I would like to select all records before 2014-03-22 date:
where date < 2014-03-22 // what I need
but below code doesn't see 2013 year's records :
SELECT * FROM `tractions` WHERE YEAR(date) <= 2014 AND MONTH(date) <= 3 and DAY(date) <= 22 and succ = 1
Is there anything wrong with:
SELECT * FROM tractions
WHERE date < '2014-03-22' -- place the date, correctly formatted, in quotes
Since this comparison doesn't use any functions, it will also allow you to use any indices setup on the date column.
This is a Mysql/sql query question but allow me to explain the context:
I would like to equip my PHP calendar with a '< PREV' and 'NEXT >' button allowing a user to easily go to the previous or next available month that has DATABASE ENTRIES AVAILABLE. If there are no database entries available, I want to disable the button (I never want the system to present an empty calendar).
Example:
User has FEB in view. JAN and MAR do not contain entries but DEC and APR do. The 'NEXT >' button then needs to switch to the April calendar. The '< PREV' button needs to switch to the December calendar.
So basically I'm looking for a single efficient query that can check if entries exist prior to and after (but not part of) the month in view.
The table has a field 'logDate' which is of type date 'Y-m-d'.
I started fumbling with the following query to check first whether or not a date exists before and after the given date but I understand that there are some things wrong with this query. For one, if there's an entry in the table for '2013-03-19' my query will spit out a 1 for prev - which of course doesn't indicate if an entry exists for months prior to March.
SELECT IF( EXISTS(SELECT dayId FROM LogbookDay
WHERE logDate < '2013-03-20' AND userId = 2), 1, 0) as prev,
IF( EXISTS(SELECT dayId FROM LogBookDay WHERE logDate > '2013-03-20'
AND userId = 2), 1, 0) as next
Modify the start date to the beginning and end of the month:
For prev, you modify to the first day of the month, by subtracting 1 less than the current day of the month. For next, you do the same, then add 1 month:
SELECT
(SELECT dayId FROM LogbookDay WHERE
logDate < ADDDDATE('2013-03-20', 1-DAY('2013-03-20')) AND userId = 2
ORDER BY logDate DESC LIMIT 1
) as PREV,
(SELECT dayId FROM LogBookDay WHERE
logDate >= ADDDATE(ADDDDATE('2013-03-20', 1-DAY('2013-03-20')), INTERVAL 1 MONTH) AND userId = 2
ORDER BY logDate ASC LIMIT 1
) as NEXT
(Or, do this in PHP, as it's likely to result in more readable code.)
Display the link differently depending on if the result is a null or a date.
It might be more elegant if you were pulling a date instead of an ID:
SELECT
(SELECT MAX(logDate) FROM LogbookDay WHERE
logDate < ADDDDATE('2013-03-20', 1-DAY('2013-03-20')) AND userId = 2
) as PREV,
(SELECT MIN(logDate) FROM LogBookDay WHERE
logDate >= ADDDATE(ADDDDATE('2013-03-20', 1-DAY('2013-03-20')), INTERVAL 1 MONTH) AND userId = 2
) as NEXT
But that depends on exactly what you're doing with the information you find. If all you're doing is creating a link to a new month, pulling the nearest date not in the same month should do the trick.
With my own query and a pointer from one of the posted answers I have been able to come up with a simple query that checks whether or not entries exist with months prior and after to the month currently in view.
Assuming month in view is March 2013:
SELECT IF( EXISTS(SELECT dayId FROM LogBookDay
WHERE logDate < '2012-03-01' AND userId = 1), 1, 0) as prev,
IF( EXISTS(SELECT dayId FROM LogBookDay
WHERE logDate > CONCAT('2012-03-',LAST_DAY('2003-02-05'))
AND userId = 1), 1, 0) as next
SELECT
if(min(logDate) < '2013-03-20', 1, 0) 'NEXT',
if(max(logDate) > '2013-03-20', 1, 0) 'PAST'
FROM LogbookDay
WHERE logDate < '2013-03-20' AND logDate > '2013-03-02'
AND userId = 2