i'm trying to use group concat with in function on mysql, it didn't give me any syntax error but i'm not sure its working.
i'm trying to do something like that:
select
case
when weekday(ps.date) in (group_concat(vd.valid_days)) then ps.date
when weekday(ps.date+1) in (group_concat(vd.valid_days)) then DATE_ADD(ps.date, INTERVAL 1 DAY)
when weekday(ps.date+2) in (group_concat(vd.valid_days)) then DATE_ADD(ps.date, INTERVAL 2 DAY)
when weekday(ps.date+3) in (group_concat(vd.valid_days)) then DATE_ADD(ps.date, INTERVAL 3 DAY)
when weekday(ps.date+4) in (group_concat(vd.valid_days)) then DATE_ADD(ps.date, INTERVAL 4 DAY)
when weekday(ps.date+5) in (group_concat(vd.valid_days)) then DATE_ADD(ps.date, INTERVAL 5 DAY)
end as valid_date
from
purchase_shopping ps
left join
purchase_region pr on pr.id = ps.idfk_region
left join
valid_weeks_days vd on vd.idfk_region = pr.id
group by ps.id
what i need basically is to return a valid date if certain day is inside a group concat from a left join. I don't know if my logic is wrong or it does not work.
Obs: The group concat function return something like that: (1,2,5), so it's supposed to work with in() function.
Sample with reworked code data:
ps.date = 2018-10-17
weekday(ps.date) = 2
group_concat(vd.valid_days) = (1,4)
then valid_date will be 2018-10-19
Perhaps you simply wants :
select (case when uc.id is not null then 'It has items' end)
from shopping_cart sc left join
user_cart uc
on uc.id = sc.idfk_cart;
You cannot use result of group_concat in same query so you have to use a subquery
select
case
when weekday(date) in valid_days then date
when weekday(date+1) in valid_days then DATE_ADD(date, INTERVAL 1 DAY)
when weekday(date+2) in valid_days then DATE_ADD(date, INTERVAL 2 DAY)
when weekday(date+3) in valid_days then DATE_ADD(date, INTERVAL 3 DAY)
when weekday(date+4) in valid_days then DATE_ADD(date, INTERVAL 4 DAY)
when weekday(date+5) in valid_days then DATE_ADD(date, INTERVAL 5 DAY)
end as valid_date
from (
select ps.date, (group_concat(vd.valid_days)) as valid_days
from
purchase_shopping ps
left join
purchase_region pr on pr.id = ps.idfk_region
left join
valid_weeks_days vd on vd.idfk_region = pr.id
group by ps.id
) as sub_query
Related
I am stucked at a dynamic where clause inside case statement.
WHAT I NEED
When i used this
SELECT col1,col2,col3
FROM Recharge r INNER join ft f ON f.date=r.date
WHERE f.Date LIKE
CASE WHEN f.Date BETWEEN (last_day(curdate() - interval 1 month) + interval 1 day) AND last_day(curdate())
THEN f.Date ELSE f.date between subdate(curdate(),interval 1 month) and (last_day(curdate() - interval 1 month)) END
ORDER BY f.id desc;
The syntax is wrong but when instead it '2022-04%'.
SELECT col1,col2,col3
FROM Recharge r INNER join ft f ON f.date=r.date
WHERE f.Date LIKE
CASE WHEN f.Date BETWEEN (last_day(curdate() - interval 1 month) + interval 1 day) AND last_day(curdate())
THEN f.Date ELSE '2022-04%' END
ORDER BY f.id desc;
It is correct but i want to change dynamically.how can i do it.
I mean that
when i run the query include date of 1-4-2022 to 30-4-2022.
The snapshot my database include data of yesterday in the begin of month i have the issue.
A case statement can only return a value and not a range. If I understand rightly it is only the start date which changes so we only need to decide the start date in the case statement. If the end date also changes we will need a second case statement.
However it looks like a simple test will return the same results
SELECT col1,col2,col3
FROM Recharge r INNER join ft f ON f.date=r.date
WHERE f.Date BETWEEN
curdate() - interval 1 month
AND
last_day(curdate())
ORDER BY f.id desc;
Re-reading your explanation I think that you really want
SELECT col1,col2,col3
FROM Recharge r INNER join ft f ON f.date=r.date
WHERE month(f.date) = month(curdate() - interval 1 day)
AND year(f.date) = year(curdate() - interval 1 day )
ORDER BY f.id desc;
db<>fiddle here
I'm using MySQL with PHP. Here is my query on which I'm getting the error.
$query =
"SELECT days.day, count(myDataTable.appId) as countf, count(myDataTable.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
group by days.day
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by days.day";
The error log is:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'left join myDataTable on days.day = myDataTable.date AND myDataTable.appId ' at line 17
It helps to properly indent your SQL so you can spot the mistakes. Indenting by the main keywords (SELECT, FROM, WHERE, HAVING, GROUP BY, and ORDER BY) will help you spot them quickly:
SELECT
days.day,
count (myDataTable.appId) as countf,
count(myDataTable.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
group by
days.day
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by
days.day
You can see that you have two GROUP BY's which won't work. Furthermore you have a LEFT JOIN hanging out in the first GROUP BY clause, which doesn't work either. Removing that first GROUP BY will get you closer:
SELECT
days.day,
count (myDataTable.appId) as countf,
count(myDataTable.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by
days.day
No you have a proper FROM clause. This is the first part that your Database looks at so it knows from where it is getting it's data and how it joins together. Your table aliases are set here and then used EVERYWHERE else in the query. Which leads you to the second problem.
You reference myDataTable up in your SELECT clause, but by the time the database is looking at your SELECT myDataTable isn't in context. The aliases n1 and n2 are though, so change these to reference your table aliases:
SELECT
days.day,
count (n1.appId) as countf,
count(n2.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by
days.day
Lastly, instead of joining your myDataTable in twice for each status, you can use a CASE statement in your SELECT:
SELECT
days.day,
SUM(CASE WHEN n1.status = 'ERROR' THEN 1 ELSE 0 END) as countf,
SUM(CASE WHEN n1.status = 'SUCCESS' THEN 1 ELSE 0 END) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id'
group by
days.day
I have the below query which is working fine and shows any missed calls on a dashboard. However if there are no results it returns no data. How do I show '0' is there are no results? Thanks
SELECT DialledNumber, COUNT(*) As Missed
FROM CALLS
WHERE destination like '%!%' AND datetime BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 day)
GROUP By DialledNumber
HAVING (DialledNumber = '500') OR (DialledNumber = '580') OR (DialledNumber = '515') OR (DialledNumber = '513') OR (DialledNumber = '514')
You can use IFNULL function in MYSQL
SELECT DialledNumber, IFNULL(COUNT(DialledNumber),0) As Missed
FROM CALLS
WHERE destination like '%!%' AND datetime BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 day)
GROUP By DialledNumber
HAVING (DialledNumber = '500') OR (DialledNumber = '580') OR (DialledNumber = '515') OR (DialledNumber = '513') OR (DialledNumber = '514')
You want to use left join rather than in:
SELECT dn.dn, COUNT(c.diallednumber) As Missed
FROM (select '500' as dn union all select '580' union all select '515' union all
select '513' union all select '514'
) dn left join
CALLS c
ON c.diallednumber = dn.dn and
c.destination like '%!%' AND
c.datetime BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 day)
GROUP By dn.dn;
As a small note, in English the word "dialed" does not have two "l"s.
This could work for you (untested):
SELECT CALLS.DialedNumber, IFNULL(MISSEDCALLS.Missed, 0) FROM CALLS
LEFT JOIN (
SELECT DialedNumber, COUNT(*) As Missed FROM CALLS
WHERE destination like '%!%' AND datetime BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 1 day)
GROUP By DialledNumber
) AS MISSEDCALLS ON MISSEDCALLS.DialedNumber = CALLS.DialedNumber
WHERE CALLS.DialledNumber IN ('500', '580', '515', '513', '514')
HI all here is a MySQL problem that uses results from a 2 table join, conditionally assess them and outputs 2 values.
Here is the database structure.
The 1st table gtpro contains
a user ID (column name id)
a samples/year number ie 2, 4 or 12 times/year (column name labSamples__yr)
The 2nd table labresults contains
that same user ID (column name idgtpro)
and a date column for the sample dates (when the samples were provided) column name date
so this query returns an overview of all id's and when were the last samples submitted for that id.
SELECT a.id, a.labSamples__yr, max(b.date) as ndate from gtpro as a
join labresults as b on a.id = b.idgtpro group by a.id
the conditions I want to evaluate looks like this.
a.labSamples__yr = 2 and ndate >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)
a.labSamples__yr = 4 and ndate >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
a.labSamples__yr = 12 and ndate >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
So if number of samples /year is 2 and the last samle date was more than 6 months ago I want to know the id and latest date of samples for that id.
I tried using CASE and IF statements but can't quite get it right. This was my latest attempt.
select id, ndate,
case when (labSamples__yr = 2 and ndate <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH))is true
then
(SELECT id from gtpro as a join labresults as b on a.id = b.idgtpro where
labSamples__yr = 2 and max(b.date) <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)) end as id
from (SELECT a.id, a.labSamples__yr, max(b.date) as ndate from gtpro as a
join labresults as b on a.id = b.idgtpro group by a.id) d
this tells me invalid use of group function.
Desperate for a bit of help
EDIT I messed up some of the names in the code above which i have now fixed.
If I understand your question correctly, you should be able to put the conditions in the where clause:
SELECT a.id, a.labSamples__yr, max(b.date) as ndate
from gtpro a join
labresults b
on a.id = b.idgtpro
where (a.labSamples__yr = 2 and b.date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)) or
(a.labSamples__yr = 4 and b.date >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)) or
(a.labSamples__yr = 12 and b.date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH))
group by a.id;
That fixes your syntax problem. But, if you want the id with the maximum date, try doing this:
select a.labSamples__yr, max(b.date) as ndate,
substring_index(group_concat(a.id order by b.date desc)) as maxid
from gtpro a join
labresults b
on a.id = b.idgtpro
where (a.labSamples__yr = 2 and b.date >= DATE_SUB(CURDATE(), INTERVAL 6 MONTH)) or
(a.labSamples__yr = 4 and b.date >= DATE_SUB(CURDATE(), INTERVAL 3 MONTH)) or
(a.labSamples__yr = 12 and b.date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH))
group by a.labSamples__yr;
Putting a.id in the group by is not going to give you the maximum id of anything.
Is this meant to be valid MySQL? I wasn't aware of "is true" being valid in a CASE statement. In fairness though I'm more familiar with Oracle and SQL Server but nevertheless... does any part of this statement work?
EDIT
Ok, here is what I have edited the code to be:
select id, ndate,
case when (labSamples__yr = 2 and ndate <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH))
then
(SELECT id from bifipro as a join labresults as b on a.id = b.idBifipro where
labSamples__yr = 2 and max(b.date) <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) where a.id=d.id) end as id
from (SELECT a.id, a.labSamples__yr, max(b.date) as ndate from bifipro as a
join labresults as b on a.id = b.idBifipro group by a.id) d
In your correlated subquery I have added a predicate of "where a.id =
d.id"
I have removed the text "is true" from your case statement (this may
be incorrect but I didnt' think it should be there.
The answer partly inspired by Tomas (sql clarification and syntax clarification) I got rid of the CASE all together. It seems nice and clean to me but I would like to hear any other suggestions
select id, labSamples__yr, ndate from
(SELECT a.id, a.labSamples__yr, max(b.date) as ndate from gtpro as a
join labresults as b on a.id = b.idgtpro group by a.id)d
where (ndate <= DATE_SUB(CURDATE(), INTERVAL 6 MONTH) and labSamples__yr = 2)
or (ndate <= DATE_SUB(CURDATE(), INTERVAL 3 MONTH) and labSamples__yr = 4)
or (ndate <= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) and labSamples__yr = 12)
Thanks for looking but it would still be nice to see a solution using a CASE statement for future reference???
I would like to combine different results from the same table as one big result.
SELECT host_name,stats_avgcpu,stats_avgmem,stats_avgswap,stats_avgiowait
FROM sar_stats,sar_hosts,sar_appgroups,sar_environments
WHERE stats_host = host_id
AND host_environment = env_id
AND env_name = 'Staging 2'
AND host_appgroup = group_id
AND group_name = 'Pervasive'
AND DATE(stats_report_time) = DATE_SUB(curdate(), INTERVAL 1 DAY)
SELECT AVG(stats_avgcpu),AVG(stats_avgmem),AVG(stats_avgswap),AVG(stats_avgiowait)
FROM sar_stats
WHERE stats_id = "stat_id of the first query" and DATE(stats_report_time)
BETWEEN DATE_SUB(curdate(), INTERVAL 8 DAY) and DATE_SUB(curdate(), INTERVAL 1 DAY)
SELECT AVG(stats_avgcpu),AVG(stats_avgmem),AVG(stats_avgswap),AVG(stats_avgiowait)
FROM sar_stats
WHERE stats_id = "stat_id of the first query" and DATE(stats_report_time)
BETWEEN DATE_SUB(curdate(), INTERVAL 31 DAY) and DATE_SUB(curdate(), INTERVAL 1 DAY)
Desired output would be something like ...
host_name|stats_avgcpu|stats_avgmem|stats_avgswap|stats_avgiowait|7daycpuavg|7daymemavg|7dayswapavg|7dayiowaitavg|30daycpuavg|30daymemavg|....etc
SQL Fiddle
http://sqlfiddle.com/#!8/4930b/3
It seems like this is what you want. I updated the first query to use proper ANSI JOIN syntax and then for the additional two queries they were joined via a LEFT JOIN on the stats_host field:
SELECT s.stats_host,
h.host_name,
s.stats_avgcpu,
s.stats_avgmem,
s.stats_avgswap,
s.stats_avgiowait,
s7.7dayavgcpu,
s7.7dayavgmem,
s7.7dayavgswap,
s7.7dayavgiowait,
s30.30dayavgcpu,
s30.30dayavgmem,
s30.30dayavgswap,
s30.30dayavgiowait
FROM sar_stats s
INNER JOIN sar_hosts h
on s.stats_host = h.host_id
INNER JOIN sar_appgroups a
on h.host_appgroup = a.group_id
and a.group_name = 'Pervasive'
INNER JOIN sar_environments e
on h.host_environment = e.env_id
and e.env_name = 'Staging 2'
LEFT JOIN
(
SELECT s.stats_host,
AVG(s.stats_avgcpu) AS '7dayavgcpu',
AVG(s.stats_avgmem) AS '7dayavgmem',
AVG(s.stats_avgswap) AS '7dayavgswap',
AVG(s.stats_avgiowait) AS '7dayavgiowait'
FROM sar_stats s
WHERE DATE(stats_report_time) BETWEEN DATE_SUB(curdate(), INTERVAL 8 DAY) AND DATE_SUB(curdate(), INTERVAL 1 DAY)
GROUP BY s.stats_host
) s7
on s.stats_host = s7.stats_host
LEFT JOIN
(
SELECT s.stats_host,
AVG(s.stats_avgcpu) AS '30dayavgcpu',
AVG(s.stats_avgmem) AS '30dayavgmem',
AVG(s.stats_avgswap) AS '30dayavgswap',
AVG(s.stats_avgiowait) AS '30dayavgiowait'
FROM sar_stats s
WHERE DATE(s.stats_report_time) BETWEEN DATE_SUB(curdate(), INTERVAL 31 DAY) AND DATE_SUB(curdate(), INTERVAL 1 DAY)
GROUP BY s.stats_host
) s30
on s.stats_host = s30.stats_host
WHERE DATE(s.stats_report_time) = DATE_SUB(curdate(), INTERVAL 1 DAY);
see SQL Fiddle with Demo