MySQL Query - Trouble with dates / between - mysql

I have a 3rd party plugin that displays events, however for some reason whenever there is an event with multiple days, it stops showing the event when the current day is past the start date, even though the end date is still in the future.
The MySQL query appears to be trying to return these with the BETWEEN part after the OR at the end but it never does. I'm not familiar enough with MySQL to see what's wrong I guess.
For instance the row I'm expecting it to return here contains:
published=1
dates=2014-04-17
enddates=2014-04-19
SQL:
SELECT a.*
FROM eventlist_events AS a
WHERE a.published = 1
AND a.dates >= '2014-04-18'
AND (DATE(a.dates) = DATE_ADD('2014-04-18',INTERVAL 0 DAY)
OR ( a.enddates IS NOT NULL
AND (DATE_ADD('2014-04-18',INTERVAL 0 DAY)
BETWEEN DATE(a.dates) AND DATE(a.enddates))) )

To satisfy your where clause for 2014-04-18 fall in between the column values:
SELECT a.* FROM eventlist_events AS a
WHERE a.published = 1
AND a.enddates IS NOT NULL
AND '2014-04-18' BETWEEN DATE(a.dates) AND DATE(a.enddates)
And if you want to fetch when a.enddates too is null, then
SELECT a.* FROM eventlist_events AS a
WHERE a.published = 1
-- AND a.enddates IS NOT NULL
AND '2014-04-18'
BETWEEN DATE( a.dates )
AND DATE( IFNULL( a.enddates, a.dates ) )

Related

How to decrease Query time of this Query with InnoDB engine

I am trying to optimize this query. Now it takes 28 seconds.
AS used to be missing in my query. After adding, query time dropped 20%
SELECT
g.id,
g.adresid,
g.senaryoid,
g.olayid,
g.gonderilecegitarih
FROM
(
SELECT
adresid
FROM
expose2.800_emsenaryolar_emgidenbulten
WHERE
olayid = '3320'
) AS s
RIGHT JOIN expose2.800_emsenaryolar_emgidenbulten AS g ON s.adresid = g.adresid
WHERE
s.adresid IS NULL
AND g.olayid = '2784'
AND g.durum = '1'
AND g.gonderilecegitarih < DATE_SUB(
'2015-05-13 15:40:15',
INTERVAL 1 DAY
)
If you use s.adresid IS NULL condition in subquery it will join faster then more rows ...
SELECT
g.id,
g.adresid,
g.senaryoid,
g.olayid,
g.gonderilecegitarih
FROM (
SELECT adresid FROM expose2.800_emsenaryolar_emgidenbulten WHERE olayid = '3320' and s.adresid IS NULL
) AS s
RIGHT JOIN expose2.800_emsenaryolar_emgidenbulten AS g ON s.adresid = g.adresid
AND g.olayid = '2784'
AND g.durum = '1'
AND g.gonderilecegitarih < DATE_SUB(
'2015-05-13 15:40:15',
INTERVAL 1 DAY
)
still this query optimized using self join.
For added speed, add this composite index to g:
INDEX(olayid, durum, gonderilecegitarih)
Please provide SHOW CREATE TABLE 800_emsenaryolar_emgidenbulten; I want to verify that you also have an index on adresid.

Find gaps in mysql Time

I have a table "channel_001" with timestamp column Time, and i did separate it by 10 minutes.
2013-01-01;00:10:04;
2013-01-01;00:20:00;
2013-01-01;00:30:02;
2013-01-01;00:40:04;
But there are missing datas. How can i detect a missing row? And then insert a row there?!
For example:
2013-01-01;00:10:04;
2013-01-01;00:20:00;
2013-01-01;00:30:02
2013-01-01;00:40:04;
2013-01-01;01:00:02;
then it would be missing:
2013-01-01;00:50:00;
I was thinking of using Join the table to itself, but im new in SQL and too much of a novice to finde the answere alone.
Any ideas?
You can find rows that don't have a "next" time with something like:
select c.*
from channel_001 c
where not exists (select 1
from channel_001 c2
where c2.timestamp > c.timestamp + interval 9 minute and
c2.timestamp < c.timestamp + interval 11 minute
);
If your table is large (tens of thousands of rows), you will probably want to use variables. The following code gets the previous timestamp:
select c.*,
(case when (#tmp := #prevts) is null then null
when (#prevts := timestamp) is null then null
else #tmp
end) as prev_timestamp
from channel_001 c cross join
(select #prevts := 0, #tmp := 0) vars
order by timestamp;
You can use this as a subquery to get gaps that are outside your range.

Group mysql results by type - but only in a certain order

Background information: I am working at a little, private pingdom.com clone.
I have a table with status checks if a website is available or not and the date of the check of course. Some of them have the status "ok", some "not ok". Now I want to group the rows by status, but only the one in the same "timeframe".
Example:
id status timestamp
1 ok 1234
2 ok 1235
3 not ok 1236
4 ok 1237
The query should make three groups with the ID's 1-2, 3 and 4. In the end I want do display that the tested site was 2 hours online, 1 hour offline and then 1 hour online again. Of course i could filter the results afterwards but I thought that this would be very inefficient with a large data set.
I have absolutely no idea where to start, because you can't group only by status. A short help for the search term would be sufficient, english is not my first language.
Try this query:
SELECT min( timestamp ) from_timestamp,
max( timestamp ) to_timestamp,
max( timestamp) - min( timestamp ) + 1 how_long,
min( id ) from_id,
max( id ) to_id,
status
FROM (
SELECT t.id,
t.timestamp,
if(#last_status = status, #group, #group:=#group+1) group_number,
#last_status := status as status
FROM table1 t
CROSS JOIN (
SELECT #last_status := null, #group:=0
) as init_vars
ORDER BY t.timestamp
) q
GROUP BY group_number
ORDER BY from_timestamp
demo: --> http://www.sqlfiddle.com/#!2/2aa1e/10

Select value in mysql but check another database at clause WHERE

I'm trying to select values from a database, but I need to check another value in another database .
I created this code, but only get 1 result and I don't know why:
SELECT `id` FROM `mc_region`
WHERE `is_subregion` = 'false'
AND lastseen < CURDATE() - INTERVAL 20 DAY
AND (SELECT id_region FROM mc_region_flags
WHERE flag <> 'expire'
AND id_region = mc_region.id
)
LIMIT 0, 30
What I've made wrong?
#Edit
I think I know why this code is not working. At database mc_region_flags not all records from the primary database has flag.
I would like to do the following:
1º Select all records on the first database, where is not subregion and lastseen is more than 20 day
2º Check if any result on the 1st database has flag 'expire', if yes, they are not included in the result.
I cant do this in 1 only SQL Code?
#Edit2
I created this code that simulate FULL JOIN but seems that WHERE is not work
SELECT *
FROM mc_region AS r RIGHT OUTER JOIN
mc_region_flags AS f ON r.id = f.id_region
UNION ALL
SELECT * from
mc_region AS r LEFT OUTER JOIN
mc_region_flags AS f
ON r.id = f.id_region
WHERE r.is_subregion = 'false'
AND f.flag = 'exipre'
AND r.lastseen < CURDATE() - INTERVAL 20 DAY
Problems WHERE not work
f.flag is not 'expire'
f.lastseen is not > 20 days
UPDATED
SELECT *
FROM `mc_region` AS r LEFT JOIN
`mc_region_flags` AS f ON r.`id` = f.`id_region`
WHERE r.`is_subregion` = 'false' AND
r.`lastseen` < CURDATE() - INTERVAL 20 DAY AND
COALESCE(f.`flag`, '-') <> 'expire'
LIMIT 0, 30;
Before the inner nested select add :
id in (select...)

Sub query or Join which is the optimal solution?

i've 2 tables, 1 user table and a table where the
outgoing emails are queued. I want to select the users
that are not online for a certain amount of time
and send them an email. I also want that, if they
already received such an email in the last 7 days
or have an scheduled email for the next 7 days, that
they are not selected.
I have 2 queries, which i think would be great if
they are working with subqueries.
As an area of which i'm not an expert in, i would
like to kindly invite you to either,
Build a subquery of the second query
Make a JOIN and exclude the second query results.
I would be far more then happy :)
Thank you for reading
SELECT
`user_id`
FROM
`user`
WHERE
DATEDIFF( CURRENT_DATE(), date_seen ) >= 7
The results of the second query should be excluded
from the query above.
SELECT
`mail_queue_id`,
`mail_id`,
`user_id`,
`status`,
`date_scheduled`,
`date_processed`
FROM
`mail_queue`
WHERE
(
DATEDIFF( CURRENT_DATE(), date_scheduled ) >= 7
OR
DATEDIFF( date_scheduled, CURRENT_DATE() ) <= 7
)
AND
(
`mail_id` = 'inactive_week'
AND
(
`status` = 'AWAITING'
OR
`status` = 'DELIVERED'
)
)
SOLUTION
SELECT
`user_id`
FROM
`user` as T1
WHERE
DATEDIFF( CURRENT_DATE(), date_seen ) >= 7
AND NOT EXISTS
(
SELECT
`user_id`
FROM
`mail_queue` as T2
WHERE
T2.`user_id` = T1.`user_id`
AND
(
DATEDIFF( CURRENT_DATE(), date_scheduled ) >= 7
OR
DATEDIFF( date_scheduled, CURRENT_DATE() ) <= 7
AND
(
`mail_id` = 'inactive_week'
AND
(
`status` = 'AWAITING'
OR
`status` = 'DELIVERED'
)
)
)
)
YOu can select the users who match the first criterion (not having logged on in the past seven days) and then "AND" that criterion to another clause using "NOT EXISTS", aliasing the same table:
select * from T where {first criterion}
and not exists
(
select * from T as T2 where T2.userid = T.userid
and ABS( DATEDIFF(datescheduled, CURRENT_DATE()) ) <=7
)
I'm not familiar with the nuances of the mysql DATEDIFF, i.e. whether it matters which date value appears in which position, but the absolute value would make it so that if the user had been sent a notice in the past 7 days or is scheduled to receive a notice in the next seven days, they would satisfy the condition, and thereby fail the NOT EXISTS condition, excluding that user from your final set.