I have a DB full of deals, and a website which will present just one of these deals if the deal is a featured deal, however I am struggling to get the right logic...
the deal that is shown on the site must
a. be within a valid date range
b. be the most recently added deal to the database
by using the following query, I am able to accomplish this:
"SELECT * FROM deals WHERE datestart < now() AND dateend > now() ORDER BY deals.deal_id DESC"
Great. however... on rare occasions a whole bunch of deals are added at once, so I need some kind of override to specify which one should be 'featured'.
I added a boolean value [featured] and tested the following query:
"SELECT * FROM deals WHERE datestart < now() AND dateend > now() ORDER BY deals.featured DESC"
It worked, but now I need to specify the featured deal, or else the featured deal will be randomly selected? whereas I only want to have it as an override.
SO I need to combine the above 2 scripts somehow.
any ideas?
thanks guys.
Add the boolean comparison to the WHERE clause and limit the number of results to 1. When ordering by the deal_id this will always return the same result.
SELECT *
FROM deals
WHERE datestart < now() AND dateend > now() AND deals.featured IS TRUE
ORDER BY deals.deal_id DESC
LIMIT 1
EDIT:
Here is an alternative so you don't have to add more to the WHERE clause.
SELECT *
FROM deals
WHERE datestart < now() AND dateend > now()
ORDER BY deals.featured DESC, deals.deal_id DESC
LIMIT 1
The order of the ORDER clause is important, if deal_id's are unique, as i presumed they were, the featured boolean would not be used if they were ordered the opposite way round.
If you just want to combine the two queries, you can just combine the where clauses - order by deal_id first, then if there are multiples with the same deal_id, it'll then sub order by whether it's featured or not:
SELECT *
FROM deals
WHERE datestart < Now()
AND dateend > Now()
ORDER BY deals.deal_id DESC,
deals.featured DESC
To get featured deals you need to check for featured IS TRUE and use UNION ALL operation to override it:
SELECT *
FROM deals
WHERE datestart < Now()
AND dateend > Now()
AND featured IS TRUE
ORDER BY deal_id DESC
UNION ALL
SELECT *
FROM deals
WHERE datestart < Now()
AND dateend > Now()
ORDER BY deal_id DESC;
I think what you 're trying to do is the following:
UPDATE deals
SET featured=1
WHERE datestart < now() AND dateend > now()
ORDER BY deal_id DESC
LIMIT 1;
Ok, so now you are trying to update the most recent valid featured deal and mark it as featured. If the rows affected count is 0 then you already have the most recent valid featured deal or there is no valid deal at all in the table (it's your choice how to react to this).
If the rows affected count is 1 then you just found a new one and you need to select it (perhaps to fill it in your site). The select statement:
SELECT *
FROM deals
WHERE datestart < now() AND dateend > now() AND featured=1
ORDER BY deal_id DESC
LIMIT 1;
Ideally you would combine these two queries into only one update-select but no way to do just that at the time.
Related
I want to get data of previous day which inserted in table
SELECT *
FROM tbl_stockpricemaster AS sm
WHERE DATE(sm.inserted_on)=DATE(NOW()- INTERVAL 1 DAY)
AND sm.stock_keyvalue='positive'
GROUP BY sm.stock_id
ORDER BY sm.stock_difprice DESC
LIMIT 5;
This is my query but the problem is that when there is no data inserted on previous day then it show blank but i want to show the last inserted record
You will have to find out which date is the previous date
This can be done using this statement:
SELECT MAX(inserted_on) FROM tbl_stockpricemaster WHERE inserted_on < DATE(NOW())
So, changing your query to this should solve your problem:
SELECT *
FROM tbl_stockpricemaster AS sm
WHERE DATE(sm.inserted_on)=(SELECT MAX(inserted_on)
FROM tbl_stockpricemaster
WHERE inserted_on < DATE(NOW()) )
AND sm.stock_keyvalue='positive'
GROUP BY sm.stock_id
ORDER BY sm.stock_difprice DESC
LIMIT 5;
I have two fields, "cont_time_published" and "cont_date_published" that I want to use to filter results in a listing of records.
select *
from news
WHERE cont_date_published < CURDATE() AND cont_time_published < CURTIME()
I am trying to achieve listing that only shows records that the publish time and publish date is in the past. So that it would filter a record that has today's date but the time is still in the future.
Results are wrong when the date is today and the time is future.
cont_date_published is "DATE" only field and cont_time_published is "TIME" Field.
If you need to get the records published in the past (today in the past hours or before) try:
SELECT *
FROM news
WHERE cont_date_published < CURDATE()
OR (cont_date_published = CURDATE() AND cont_time_published < CURTIME());
sorry my mistake, forgot the OR
Try this
SELECT *
FROM news
WHERE (cont_date_published < CURDATE() ) AND ( cont_time_published < CURTIME() )
ORDER BY id DESC;
You can CAST to an actual date:
WHERE CAST(CONCAT(cont_date_published, ' ', cont_time_published) AS DATETIME)<NOW()
... but this will possibly prevent query optimiser from using indexes (if any). An alternative would be:
WHERE cont_date_published<CURDATE() OR
(cont_date_published=CURDATE() AND cont_time_published<CURTIME())
Of course, all this extra work could be easily avoided with a proper database design that makes use of a single DATETIME column:
WHERE cont_published<NOW()
select * from news WHERE cont_date_published < CURDATE()
This will be enough to get the records that are Published in the Past.
According to this documentation from my understanding using INTERVAL 8 DAY will return any records greater than 8 days.
In my statement $moztimestampnow is the current date in this format 2015-05-21 and moztimestamp pertains to the column in the DB that contains the other earlier date in which I need to calculate with.
I am not sure if I am able to use moztimestamp as the column name in this statement and it is not working.
How do I get the difference in days?
$moztimestampnow = date('Y-m-d');
SELECT *,DATEDIFF('$moztimestampnow',moztimestamp) INTERVAL 8 DAYS FROM backlinks WHERE user_id = '$user_id' LIMIT 10
First, you a misinterpreting the documentation. The interval keyword is for adding values to dates. If you want to filter data, you need to use the where clause.
In your case, the best where clause looks like this:
SELECT bl.*, DATEDIFF('$moztimestampnow', moztimestamp)
FROM backlinks bl
WHERE user_id = '$user_id' and
moztimestamp <= DATE_SUB(CURDATE(), INTERVAL 8 DAY)
LIMIT 10
This can take advantage of an index on backlinks(user_id, moztimestamp). In addition, you probably should have an ORDER BY clause. That is expected when using LIMIT.
Your syntax doesn't make sense. Try something like:
SELECT *
FROM backlinks
WHERE DATE_SUB(moztimestamp, INTERVAL 8 DAY) > '$moztimestampnow'
AND user_id = '$user_id'
LIMIT 10
I don't follow your objective, so you may have to change the order and direction in the first WHERE clause.
I have a query like below
SELECT * FROM mdata ORDER BY ABS(DATEDIFF(NOW(), orderdate)) LIMIT 1
returns the Nearest - Closest Time from a DateTime field type (orderdate) and this includes fields after current time, as well. How can I retrieve the fields AFTER now?
How can I retrieve the fields AFTER now?
This simple query will do that:
-- Return all rows after now
SELECT * FROM mdata WHERE orderdate > NOW()
If you want to return just one after now but not equal to now, do this:
-- Return first row AFTER now
SELECT * FROM mdata WHERE orderdate > NOW() ORDER BY orderdate ASC LIMIT 1
NOW() reference
What could be wrong with my sql query here , I'd like to retrieve data from both tables meeting a WHERE condition
SELECT *, UNIX_TIMESTAMP(i.sent_date) AS udate
FROM ibc_sent_history as i INNER JOIN
ibc_messages as u
ON i.msg_ids = u.id
WHERE (i.sent_date >= '02-02-2013' AND i.sent_date <= '02-02-2014')
ORDER BY i.sent_date
LIMIT 200
Assuming your ibc_sent_history.sent_date datatype is DATETIME, here's a way to refactor this query. (This will work even if the datatype is DATE). You need to change your date input string format from 02-02-2013 to the more standard '2014-02-02` (YYYY-MM-DD).
SELECT whatever, whatever
FROM ibc_sent_history AS i
INNER JOIN ibc_messages AS u ON i.msg_ids = u.id
WHERE i.sent_date >= '2013-02-02'
AND i.sent_date < '2014-02-02' + INTERVAL 1 DAY
ORDER BY i.sent_date DESC
LIMIT 200
I changed the ORDER BY to include DESC. This is to return the most recent items, not the oldest. If that's not what you need, take off the DESC.
I changed the date formatting.
I changed the end of your selection range to
i.sent_date < '2014-02-02` + INTERVAL 1 DAY
That's because
i.sent_date <= '2014-02-02`
will include items that occur precisely at midnight on 2-Feb-2014, but won't include any other items on that day. What you probably want are items that occurred up to but NOT including midnight on the next day.
I don't know MySQL very well, but in SQL Fiddle when I run:
CAST('2014-02-02' AS DATE)
I get a date, when I run
CAST('02-02-2014' AS DATE)
I get NULL, so seems like your date format is wrong.
Demo: SQL Fiddle