Select value in mysql but check another database at clause WHERE - mysql

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...)

Related

Left Join in MySQL wrong output table

I did a left join to obtain the data that I wanted. However, the output table has 4 columns, where the first 3 have the right data but the last column doesn't match with the other 3. So, to be specific in one table I have the names and in the other I have dates, usernames, and "comments". What makes it difficult is that I need to have only the most recent dates in a table that is changed daily. This is my query:
SELECT CONCAT(ur.USR_FIRSTNAME, ur.USR_LASTNAME) AS 'NAME',
aav.USR AS 'USERNAME',
IF(aav.TIME_STAMP > NOW() + INTERVAL -4 HOUR,
aav.AVAILABLE_DATE,MAX(aav.AVAILABLE_DATE)) AS 'DATE_AVAILABLE',
aav.COMMENTS AS 'COMMENTS'
FROM wi_workflow.USERS ur LEFT JOIN fii_tables.available_log aav ON ur.USR_USERNAME = aav.USR and ur.USR_UID = aav.USR_UID
LEFT JOIN fii_tables.available_log aav2 ON(aav.COMMENT = aav2.COMMENT)
WHERE ur.USR_POSITION = 'EDE'
AND ur.USR_STATUS = 'ACTIVE'
AND aav.TIME_STAMP > NOW() + INTERVAL - 45 DAY
GROUP BY 1;
Can somebody give me hint on how to have the last column matching the other 2?
Thanks.
I solved my problem this is the query that I used:
SELECT aev.ede_name,
aav.available_date,
aav.COMMENT AS 'COMMENT',
IF(aav.AVAILABLE_DATE < NOW() + INTERVAL 5 DAY, "AVAILABLE THIS WEEK",'NOT AVAILABLE') AS 'AVAILABILITY'
FROM fii_tables.available_log aav
INNER JOIN (SELECT aav.`USR` AS usr,max(aav.TIME_STAMP) AS `TIME_STAMP` from fii_tables.available_log aav group by aav.USR;) lts ON ( lts.usr = aav.usr AND lts.time_stamp = aav.time_stamp )
LEFT JOIN wf_workflow.actual_ede_v aev ON(aav.usr = aev.usr_username)
where aev.ede_name is not null
GROUP BY aav.usr, aav.time_stamp;

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.

MySQL Query - Trouble with dates / between

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 ) )

mysql find date where no row exists for previous day

I need to select how many days since there is a break in my data. It's easier to show:
Table format:
id (autoincrement), user_id (int), start (datetime), end (datetime)
Example data (times left out as only need days):
1, 5, 2011-12-18, 2011-12-18
2, 5, 2011-12-17, 2011-12-17
3, 5, 2011-12-16, 2011-12-16
4, 5, 2011-12-13, 2011-12-13
As you can see there would be a break between 2011-12-13 and 2011-12-16. Now, I need to be able say:
Using the date 2011-12-18, how many days are there until a break:
2011-12-18: Lowest sequential date = 2011-12-16: Total consecutive days: 3
Probably: DATE_DIFF(2011-12-18, 2011-12-16)
So my problem is, how can I select that 2011-12-16 is the lowest sequential date? Remembering that data applies for particular user_id's.
It's kinda like the example here: http://www.artfulsoftware.com/infotree/queries.php#72 but in the reverse.
I'd like this done in SQL only, no php code
Thanks
SELECT qmin.start, qmax.end, DATE_DIFF( qmax.end, qmin.start ) FROM table AS qmin
LEFT JOIN (
SELECT end FROM table AS t1
LEFT JOIN table AS t2 ON
t2.start > t1.end AND
t2.start < DATE_ADD( t1.end, 1 DAY )
WHERE t1.end >= '2011-12-18' AND t2.start IS NULL
ORDER BY end ASC LIMIT 1
) AS qmax
LEFT JOIN table AS t2 ON
t2.end < qmin.start AND
t2.end > DATE_DIFF( qmin.start, 1 DAY )
WHERE qmin.start <= '2011-12-18' AND t2.start IS NULL
ORDER BY end DESC LIMIT 1
This should work - left joins selects one date which can be in sequence, so max can be fineded out if you take the nearest record without sequential record ( t2.anyfield is null ) , same thing we do with minimal date.
If you can calculate days between in script - do it using unions ( eg 1. row - minimal, 2. row maximal )
Check this,
SELECT DATEDIFF((SELECT MAX(`start`) FROM testtbl WHERE `user_id`=1),
(select a.`start` from testtbl as a
left outer join testtbl as b on a.user_id = b.user_id
AND a.`start` = b.`start` + INTERVAL 1 DAY
where a.user_id=1 AND b.`start` is null
ORDER BY a.`start` desc LIMIT 1))
DATEDIFF() show difference of the Two days, if you want to number of consecutive days add one for that result.
If it's not a beauty contents then you may try something like:
select t.start, t2.start, datediff(t2.start, t.start) + 1 as consecutive_days
from tab t
join tab t2 on t2.start = (select min(start) from (
select c1.*, case when c2.id is null then 1 else 0 end as gap
from tab c1
left join tab c2 on c1.start = adddate(c2.start, -1)
) t4 where t4.start <= t.start and t4.start >= (select max(start) from (
select c1.*, case when c2.id is null then 1 else 0 end as gap
from tab c1
left join tab c2 on c1.start = adddate(c2.start, -1)
) t3 where t3.start <= t.start and t3.gap = 1))
where t.start = '2011-12-18'
Result should be:
start start consecutive_days
2011-12-18 2011-12-16 3

mysql day report query

The query below gives me a report of items that are out for an equipment rental company. this is a super complicated query that takes almost 20 seconds to run. This is obviously not the correct way to get the data that I'm looking for. I build this query from PHP and add in the start date of 02-01-2011 and the end date of 03-01-2011, the product code (p_code = 1) and product pool (i_pool =1). Those 4 pieces of information are passed to a PHP function and injected into the following sql to return the report I need for a calendar control displaying how many items are out. My question is: Is there any way to simplify or do this better, or run more efficiently, using better joins or a better way to display the individual days.
SELECT DISTINCT reportdays.reportday, count(*)
FROM
(SELECT '2011-02-01' + INTERVAL a + b DAY reportday
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
UNION SELECT 8 UNION SELECT 9 ) d,
(SELECT 0 b UNION SELECT 10 UNION SELECT 20
UNION SELECT 30 UNION SELECT 40) m
WHERE '2011-02-01' + INTERVAL a + b DAY < '2011-03-01'
ORDER BY a + b) as reportdays
JOIN rental_inv as line
ON DATE(FROM_UNIXTIME(line.ri_delivery_dte)) <= reportdays.reportday
AND DATE(FROM_UNIXTIME(line.ri_pickup_dte)) >= reportdays.reportday
LEFT OUTER JOIN rental_in as rent on line.ri_num = rent.ri_num
LEFT OUTER JOIN rental_cancels cancelled on rent.ri_num = cancelled.ri_num
LEFT OUTER JOIN inv inventory on line.i_num = inventory.i_num
LEFT OUTER JOIN product ON inventory.p_code = product.p_code
WHERE rent.ri_extend = 0 -- disregard extended rentals
AND cancelled.ri_num is null -- disregard cancelled rentals
AND inventory.p_code = 1
AND inventory.i_pool = 1
GROUP BY reportdays.reportday
If there is any other information needed, let me know and I'll post it.
You can use:
SELECT DATE(ri_delivery) as day,
count(*) as itemsout,
FROM rental_inv
GROUP BY day;
I'm not sure if you need this or a different thing.
SELECT dates.day, count (*)
FROM rental_inv line
INNER JOIN (SELECT DATE(ri_delivery_dte) as day FROM rental_inv
WHERE ri_delivery_dte >= '2011/02/01'
AND ri_delivery_dte <= '2011/02/28'
GROUP BY day
UNION
SELECT DATE(ri_pickup_dte) as day FROM rental_inv
WHERE ri_pickup_dte >= '2011/02/01'
AND ri_pickup_dte <= '2011/02/28'
GROUP BY day) dates
ON line.ri_delivery_dte <= dates.day and line.ri_pickup_dte >= dates.day
LEFT JOIN rental_cancels canc on line.ri_num = canc.ri_num
LEFT JOIN rental_in rent on line.ri_num = rent.ri_num
WHERE canc.ri_num is null
AND rent.ri_extend = 0
GROUP BY dates.day
to find all days:
SELECT DATE(IFNULL(ri_delivery,ri_pickup)) AS date FROM rental_inv AS dateindex WHERE [YEAR-MONTH-1] <= ri_delivery <= LAST_DAY([YEAR-MONTH-1]) OR [YEAR-MONTH-1] <= ri_pickup <= LAST_DAY([YEAR-MONTH-1]) GROUP BY date HAVING NOT ISNULL(date)
to find items out
SELECT COUNT(id) FROM rental_inv WHERE ri_pickup = [DATE];
to find items in
SELECT COUNT(id) FROM rental_inv WHERE ri_delivery = [DATE];
to find balance
SELECT COUNT(out.id) - COUNT(in.id) FROM rental_inv AS out INNER JOIN rental_inv AS in
ON DATE(out.ri_pickup) = DATE(in.ri_delivery) WHERE out.ri_pickup = [DATE] OR in.ri_delivery = [DATE]
You probably can join up everything but since its procedure its more clear;
I am not sure if this would be the exact answer to your problem but I would do something like this I guess. (I didn't use any SQL editor so u need to check syntax I guess)
SELECT
reportdays.d3 as d,
( COALESCE(outgoing.c1,0) - COALESCE(incoming.c2,0) ) as c
FROM
-- get report dates
(
SELECT DATE(FROM_UNIXTIME(COALESCE(l3.ri_delivery_dte, l3.ri_pickup_dte)) d3
FROM rental_inv l3
WHERE
(l3.ri_delivery_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l3.ri_delivery_dte < UNIX_TIMESTAMP('2011-03-01'))
OR (l3.ri_pickup_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l3.ri_pickup_dte < UNIX_TIMESTAMP('2011-03-01'))
GROUP BY d3
) as reportdays
-- get outgoing
LEFT JOIN (
SELECT DATE(FROM_UNIXTIME(l1.ri_delivery_dte)) as d1, count(*) as c1
FROM rental_inv l1
LEFT JOIN rental_cancels canc1 on l.ri_num = canc1.ri_num
LEFT JOIN rental_in rent1 on l.ri_num = rent1.ri_num
WHERE
l1.ri_delivery_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l1.ri_delivery_dte < UNIX_TIMESTAMP('2011-03-01')
AND canc1.ri_num is null
AND rent1.ri_extend = 0
GROUP BY d1
) as outgoing ON reportdays.d3 = outgoing.d1
-- get incoming
LEFT JOIN (
SELECT DATE(FROM_UNIXTIME(l2.ri_pickup_dte)) as d2, count(*) as c2
FROM rental_inv l2
LEFT JOIN rental_cancels canc2 on l2.ri_num = canc2.ri_num
LEFT JOIN rental_in rent2 on l2.ri_num = rent2.ri_num
WHERE
l2.ri_pickup_dte >= UNIX_TIMESTAMP('2011-02-01')
AND l2.ri_pickup_dte < UNIX_TIMESTAMP('2011-03-01')
AND canc2.ri_num is null
AND rent2.ri_extend = 0
GROUP BY d2
) as incoming ON reportdays.d3 = incoming.d2