I am having a trouble with OR
condition inside the SELECT
.
I want a simple result if one condition is matched and rest OR
condition should not be use.
What i want is:
I have some users shared records and i would like to email them the newest items shared on my website.
For me: Newest Items will be least two days older
Like Today is 9th so i would like to pull all records of 7th. but if i didn't get any record of 7th then i would like to pull all record of 6th (3 days older from today). if i didn't get any records on 6th then i would like to pull 1 day older from today.
for all this i have used OR
in my SELECT
query like this:
SELECT `tg`.* FROM `tblgallery` AS `tg` WHERE (
(tg.added_date BETWEEN '2014-07-07 00:00:00' AND '2014-07-08 00:00:00') OR
(tg.added_date BETWEEN '2014-07-06 00:00:00' AND '2014-07-07 00:00:00') OR
(tg.added_date BETWEEN '2014-07-08 00:00:00' AND '2014-07-09 00:00:00') )
And i have records in my database for dates:
2014-07-06
2014-07-07
and when i run this query it gives me all record of both dates.
But I need to pull only record of 2014-07-07
not of both.(I have mentioned above.)
I know i can do this by using multiple Select
and i think that will not be a good idea to request to database again and again.
My Question is : How to pull data from database if the first match is true? and skip all data of rest dates?
OR
Is there any other way to do this?
Please Help
Usually one would just work with LIMIT
, which is not applicable here, since there might be many rows per day. What I do is quite similar to LIMIT
.
SELECT * FROM (
SELECT
tg.*,
@gn := IF(DATE(tg.added_date) != @prev_date, @gn + 1, @gn) AS my_group_number,
@prev_date := DATE(tg.added_date)
FROM tblgallery tg
, (SELECT @gn := 0, @prev_date := CURDATE()) var_init
ORDER BY FIELD(DATE(tg.added_date), CURDATE() - INTERVAL 1 DAY, CURDATE() - INTERVAL 3 DAY, CURDATE() - INTERVAL 2 DAY) DESC
) sq
WHERE my_group_number = 1;
Here's how it works.
With this line
, (SELECT @gn := 0, @prev_date := CURDATE()) var_init
the variables are initialized.
Then the ORDER BY
is important! The FIELD()
function sorts the rows from 2 days ago
(gets value 3), to 3 days ago
(gets value 2), to 1 day ago
(gets value 1). Everything else gets value 0.
Then in the SELECT
clause the order is also important.
With this line
@gn := IF(DATE(tg.added_date) != @prev_date, @gn + 1, @gn) AS my_group_number,
the variable @gn
is incremented when the date of the current row is different from the date of the previous row.
With this line
@prev_date := DATE(tg.added_date)
the date of the current row is assigned to the variable @prev_date
. In the line above it still has the value of the previous row.
Now those entries have a 1
in column my_group_number
that have the most recent date in the order
2 days ago
3 days ago
yesterday
4 days ago
5 days ago
...
Try this Query:
SELECT GalleryID, PixName, A.added_date
FROM tblGallery A
INNER JOIN (
SELECT added_date FROM tblGallery
WHERE added_date <= DATE_SUB('2014-07-09 00:00:00', interval 2 day)
GROUP BY added_date
ORDER BY added_date DESC
LIMIT 1 ) B
ON A.added_date = B.added_date
See my SQL Fiddle Demo
And even if the date is more than 2 days older it will still work. See here the Demo below wherein the latest is 4 days older from July 9, 2014
See the 2nd Demo
And if you want the current date instead of literal date like here then you could use CURDATE()
function instead. Like one below:
SELECT GalleryID, PixName, A.added_date
FROM tblGallery A
INNER JOIN (
SELECT added_date FROM tblGallery
WHERE added_date <= DATE_SUB(CURDATE(), interval 2 day)
GROUP BY added_date
ORDER BY added_date DESC
LIMIT 1 ) B
ON A.added_date = B.added_date
See 3rd Demo
Well, I'm not being able to solve the multi OR issue but this is how could you get records being added last two days. Change the interval or the CURDATE() in order to fit your needs.
SELECT id, date_added
FROM gallery
WHERE date_added BETWEEN CURDATE() - INTERVAL 2 DAY AND CURDATE()
ORDER BY date_added
Check the SQL Fiddel
It is not about how OR works in MySQL. I think you are misunderstanding where part by looking at your discussion with @B.T. It will be executed for each record. so if one of the record evaluates to false for the first condition then it will evaluate the second condition for that particular record and so on so if any condition evaluates to true by considering all the conditions then that will become part of your result set.
Try this query.
SELECT `tg`.* FROM `tblgallery` AS `tg` WHERE tg.added_date = (
select date (
select distinct(tg.added_date) date from tblgallery as tg
) as t1 order by case
when date between '2014-07-07 00:00:00' AND '2014-07-08 00:00:00'
then 1
when date between '2014-07-06 00:00:00' AND '2014-07-07 00:00:00'
then 2
when date between '2014-07-08 00:00:00' AND '2014-07-09 00:00:00'
then 3
else 4
end limit 1);
Here's what I am doing in this query.
Note: I have note tested it yes, so you may need to do some changes to the query.