mysql query "Invalid use of group function" - mysql

I have query like this
SELECT id_order_history,
( MAX(DATE(date_add)) - MIN(DATE(date_add))) AS selisih
FROM ps_order_history
WHERE id_order_state IN ('2', '48', '49', '50')
AND MONTH (date_add) = '05'
AND YEAR (date_add) = '2016'
AND (MAX(DATE(date_add)) - MIN(DATE(date_add)) > 5)
GROUP BY id_order
and it has an issue in
AND (MAX(DATE(date_add)) - MIN(DATE(date_add)) > 5)
How to solve it ?

Related

mysql error: FUNCTION asterisk.SUM does not exist. (Apache superset)

I connected the mysql database and ran a direct sql query and I got the correct table, I wanted to visualize it and clicked the "Explore" button, but I got the error: "mysql error: FUNCTION asterisk.SUM does not exist. Check the ' Function Name Parsing and Resolution 'section in the Reference Manual "Please tell me where I made a mistake, thanks.
working sql request
error
My sql request:
SELECT DATE_FORMAT(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM(end-start)),'%H:%i:%S') AS Call_duration,
case
when substring(dstchannel,5,4) = '1000' then 'Name1'
when substring(dstchannel,5,4) = '2000' then 'Name2'
when substring(dstchannel,5,4) = '3000' then 'Name3'
when substring(dstchannel,5,4) = '4000' then 'Name4'
when substring(dstchannel,5,3) = '100' then 'Other'
end AS Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in'
AND disposition = 'ANSWERED'
AND end-start > 0
group by DATE_FORMAT(start, '%Y-%m-%d'), 4
order by 1 desc
My request works correctly, but when I try to create a chart, superset changes the request and it has a line break after SUM. Сan I fix this without changing the database configuration?
Superset out query:
SELECT `Date` AS `Date`,
`Type` AS `Type`,
`Call_duration` AS `Call_duration`,
`Operator` AS `Operator`,
`Number_of_calls` AS `Number_of_calls`
FROM
(SELECT DATE_FORMAT
(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM
(end-start)), '%H:%i:%S') AS Call_duration,
case
when substring(dstchannel, 5, 4) = '1000' then 'Name1'
when substring(dstchannel, 5, 4) = '2000' then 'Name2'
when substring(dstchannel, 5, 4) = '3000' then 'Name3'
when substring(dstchannel, 5, 4) = '4000' then 'Name4'
when substring(dstchannel, 5, 3) = '100' then 'Other'
end AS
Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in'
AND disposition = 'ANSWERED'
AND end-
start > 0
group by DATE_FORMAT
(start, '%Y-%m-%d'),
4
order by 1 desc) AS expr_qry
LIMIT 1000;
Your group by doesn't match the select columns. Try:
SELECT DATE_FORMAT(start, '%Y-%m-%d') AS Date,
disposition AS Type,
DATE_FORMAT(SEC_TO_TIME(SUM(end-start)), '%H:%i:%S') AS Call_duration,
(case when substring(dstchannel,5,4) = '1000' then 'Name1'
when substring(dstchannel,5,4) = '2000' then 'Name2'
when substring(dstchannel,5,4) = '3000' then 'Name3'
when substring(dstchannel,5,4) = '4000' then 'Name4'
when substring(dstchannel,5,3) = '100' then 'Other'
end) AS Operator,
count(*) AS Number_of_calls
FROM cdr
WHERE dcontext = 'call-in' AND
disposition = 'ANSWERED'
end > start
group by DATE_FORMAT(start, '%Y-%m-%d'), type, call_duration, operator
order by 1 desc

How to check values in mysql for preceeding rows and using them to find sum

I have to find the time, that the system that is based on this table has elapsed while having code '100', so firstly i thought that I have to find the newest row of the xID group and after that, check the previous rows if their code is 100, if so i have to proceed with previous previous row till it gets a 200 value, after that it finds the time from the following row of 200 hundred till now (value 100).
ID xID createdDate CODE
1 '1', '2019-07-27 11:52:01', '100'
2 '1', '2019-07-27 11:54:01', '200'
3 '2', '2019-09-03 05:10:02', '200'
4 '2', '2019-09-03 05:12:02', '200'
5 '3', '2019-09-02 05:12:02', '200'
6 '3', '2019-09-02 05:12:02', '100'
7 '3', '2019-09-02 05:12:02', '200'
8 '4', '2019-09-02 05:13:02', '200'
9 '5', '2019-09-03 05:10:03', '200'
10 '6', '2018-12-13 05:03:02', '200'
So this query must for each group of xID find the total time for which the system has been with code 100 until now. Hope I've been clear. And here is the sql so far.
select id, createdDate, code
from wlogs
where id in (
select max(id)
from wlogs
group by xid
)
order by xid;
EDIT:
MYSQL VERSION 8.0
RESULT must be something like this where the column totTimeWithCode100 must show the time in seconds or minutes doesn't matter, for each type of xID.
xID totTimeWithCode100
'1', '500'
'2', '2'
'3', '33'
'4', '200'
'5', '40'
'6', '200'
These rows
Prior to MySQL 8.0, we can use of user-defined variables (in a way that is unsupported) in carefully crafted SQL that takes advantage of behavior that is repeatably observed but not guaranteed. (The MySQL Reference Manual warns specifically about this usage of user-defined variables.)
Something like this:
SELECT s.xid AS `xID`
, IFNULL(SUM(s.secs_in_code100),0) AS `totTimeWithCode100`
FROM (
SELECT IF(#prev_xid = t.xid AND #prev_code = 100, TIMESTAMPDIFF(SECOND,#prev_date,t.createddate),0) AS secs_in_code100
, #prev_xid := t.xid AS xid
, #prev_date := t.createddate AS createddate
, #prev_code := t.code AS code
FROM ( SELECT #prev_xid := ''
, #prev_date := '1970-01-02 03:00'
, #prev_code := ''
) i
CROSS
JOIN wlogs t
ORDER
BY t.xid
, t.createddate
) s
GROUP BY s.xid
ORDER BY s.xid
With MySQL 8.0, we can avoid the user-defined variables by using analytic/window functions.
You can get the result you want by finding all the rows with CODE = 100 for a given xID that are immediately followed (in time) by a row with CODE != 100. This can be done by LEFT JOINing the rows with CODE != 100 to the preceding row if that row has CODE = 100:
SELECT w.xID, COALESCE(SUM(TIMESTAMPDIFF(SECOND, w1.createdDate, w2.createdDate)), 0) AS totTimeWithCode100
FROM (SELECT DISTINCT xID FROM wlogs) w
LEFT JOIN (SELECT *
FROM wlogs
WHERE CODE = 100) w1 ON w1.xID = w.xID
LEFT JOIN wlogs w2 ON w2.xID = w1.xID
AND w2.createdDate = (SELECT MIN(createdDate)
FROM wlogs w3
WHERE w3.xID = w1.xID AND
w3.createdDate > w1.createdDate)
GROUP BY w.xID
ORDER BY w.xID;
Demo on dbfiddle

How to SUM result both SUMs SQL?

Using this query I try to sum result of both SUM function:
select
DAY(created_at) AS day,
SUM(if(status = '1', 1, 0)) AS result,
SUM(if(status = '2', 1, 0)) AS noresult,
SUM(result + noresult)
from `clients` where `doctor_id` = 2 and MONTH(created_at) = MONTH(CURRENT_TIMESTAMP) group by `day`
I try to do that in this line:
SUM(result + noresult)
Try this:
select
DAY(created_at) AS day,
SUM(if(status = '1', 1, 0)) AS result,
SUM(if(status = '2', 1, 0)) AS noresult,
SUM(if(status in ('1', '2'), 1, 0))
from `clients`
where `doctor_id` = 2 and MONTH(created_at) = MONTH(CURRENT_TIMESTAMP)
group by `day`
You can't use alias in select columns name you must repeat the code
select
DAY(created_at) AS day,
SUM(if(status = '1', 1, 0)) AS result,
SUM(if(status = '2', 1, 0)) AS noresult,
SUM(if(status = '1', 1, 0)) + SUM(if(status = '2', 1, 0)) AS all_result
from `clients` where `doctor_id` = 2 and MONTH(created_at) = MONTH(CURRENT_TIMESTAMP) group by `day`
you must repeat the code because the different SQL clause are processed in a specific order (first from then where then select and and group by .... etc.. ) so at the moment of the select parsing the alias are not available to the sql engine
As several other people have stated, you cannot use aliases in your select statement. However, to keep it cleaner, you could combine both conditions rather than summing both SUM fields.
select
DAY(created_at) AS day,
SUM(if(status = '1', 1, 0)) AS result,
SUM(if(status = '2', 1, 0)) AS noresult,
SUM(if(status = '1' OR status = '2', 1, 0)) AS newcolumn
from `clients` where `doctor_id` = 2 and MONTH(created_at) = MONTH(CURRENT_TIMESTAMP) group by `day`

Case in where condition to calculate individual totals

select
Count(*)
from gl
join TRVMAINDATA msit
on gl.TRANSACTIONID = msit.CHARGETRANSACTIONID
where gl.CREATEDDATETIME >= DATEADD(MONTH,-2,getdate()) AND
datediff(DAY,gl.BUSINESSPROCESSDATE,gl.CREATEDDATETIME)>=4 AND
gl.MARKETCODE In('535','532','056','050','039','036','034','033','030','029','027','023','022','021','018','015','012','011','010','009','007','006','005','002','001' ) and DATEADD(MONTH,DATEDIFF(MONTH,0,gl.CREATEDDATETIME),0) = '2/1/2017 12:00:00 AM'
The above code gives the total for market code mentioned.
But i also want the market code for other code which doesn't belog here. for example
select
Count(*)
from gl
join TRVMAINDATA msit
on gl.TRANSACTIONID = msit.CHARGETRANSACTIONID
where gl.CREATEDDATETIME >= DATEADD(MONTH,-6,getdate()) AND
datediff(DAY,gl.BUSINESSPROCESSDATE,gl.CREATEDDATETIME)>=0
and
DATEADD(MONTH,DATEDIFF(MONTH,0,gl.CREATEDDATETIME),0) = '2/1/2017 12:00:00 AM'
AND
(case
when gl.MARKETCODE In('535','532','056','050','039','036','034','033','030','029','027','023','022','021','018','015','012','011','010','009','007','006','005','002','001') then 'Proprietary'
when gl.MARKETCODE='037' then 'US'
else 'partner'
end )
Is it possible to calculate totals of other market codes in one sql query or do i have to calculate individually?
I think you would like to do count with case when in select statement like this:
SELECT COUNT(CASE
WHEN gl.marketcode IN ( '535', '532', '056', '050',
'039', '036', '034', '033',
'030', '029', '027', '023',
'022', '021', '018', '015',
'012', '011', '010', '009',
'007', '006', '005', '002', '001' ) THEN 1
ELSE NULL
END) AS `Proprietary`,
COUNT(CASE
WHEN gl.marketcode = '037' THEN 1
ELSE NULL
END) AS `US`,
COUNT(CASE
WHEN gl.marketcode NOT IN ( '535', '532', '056', '050',
'039', '036', '034', '033',
'030', '029', '027', '023',
'022', '021', '018', '015',
'012', '011', '010', '009',
'007', '006', '005', '002',
'001', '037' ) THEN 1
ELSE NULL
END) AS `partner`
FROM gl
JOIN trvmaindata msit
ON gl.transactionid = msit.chargetransactionid
WHERE gl.createddatetime >= DATEADD(month, -2, GETDATE())
AND DATEDIFF(day, gl.businessprocessdate, gl.createddatetime) >= 4
AND DATEADD(month, DATEDIFF(month, 0, gl.createddatetime), 0) = '2/1/2017 12:00:00 AM'

MySQL - conditional select in group

I have a simple table with several rows and I would like to group them by id_room and select value only when condition is true. Problem is that condition is always false even there is a row with right date column year_month.
Here is schema:
CREATE TABLE tbl_account_room (
`id` int,
`year_month` date,
`value` int,
`id_room` int
);
INSERT INTO tbl_account_room
(`id`, `year_month`, `value`, `id_room`)
VALUES
(1, '2016-08-01', 1, 300),
(2, '2016-09-01', 2, 300),
(3, '2016-10-01', 3, 300);
and here query:
SELECT
(case when '2016-10-01' = ar.year_month then ar.value else 0 end) as total
FROM tbl_account_room AS ar
WHERE ar.year_month >= "2016-08-01"
AND ar.year_month <= "2016-11-01"
and ar.id_room = '300'
GROUP BY ar.id_room
LIMIT 10
Here is SQL Fiddle
In column total I'm getting 0 and I would like to get value 3 because year_month is 2016-10-01. Why this happens?
You certainly don't need that CASE condition and include that condition in your WHERE clause rather like
SELECT
ar.value as total,
GROUP_CONCAT(ar.year_month)
FROM tbl_account_room AS ar
WHERE ar.year_month = '2016-10-01'
GROUP BY ar.id_room;
Not sure why you want the result like that, here you can use self join to do that:
SELECT
MAX(t1.value) as total,
GROUP_CONCAT(ar.year_month)
FROM tbl_account_room AS ar
LEFT JOIN tbl_account_room AS t1
ON ar.id_room = t1.id_room
AND ar.year_month = t1.year_month
AND t1.year_month = '2016-10-01'
WHERE ar.year_month >= "2016-08-01"
AND ar.year_month <= "2016-11-01"
and ar.id_room = '300'
GROUP BY ar.id_room
LIMIT 10;
and here is SQLFiddle Demo.