[HY000][1111] Invalid use of group function - mysql

I have searched a lot ,but none of other questions with error 1111 solves my problem.
My needs are to count the distinct phone number of some id
The following code works:
SELECT
a.id_borrow_application,
count(DISTINCT c.phone_no) CVG_CALL_OUT_COUNTS_6M
FROM t_snow_borrow_application_id a
JOIN t_snow_call_mobile b
JOIN t_snow_call_record_201612 c ON
(
a.id_borrow_application = b.id_borrow_application
AND b.id = c.id_call_mobile
)
WHERE c.call_type = 0
GROUP BY a.id_borrow_application;
But when I want to write 4 similar queries together,the error in title
happens.
[HY000][1111] Invalid use of group function
SELECT
a.id_borrow_application,
sum(CASE WHEN call_type = 0
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_OUT_COUNTS_6M,
sum(CASE WHEN call_type = 0 AND c.days <= 30
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_OUT_COUNTS_1M,
sum(CASE WHEN call_type = 1
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_IN_COUNTS_6M,
sum(CASE WHEN call_type = 1 AND c.days <= 30
THEN count(DISTINCT c.phone_no)
ELSE 0 END) CVG_CALL_IN_COUNTS_1M
FROM t_snow_borrow_application_id a
JOIN t_snow_call_mobile b
JOIN t_snow_call_record_201612 c ON
(
a.id_borrow_application = b.id_borrow_application
AND b.id = c.id_call_mobile
)
GROUP BY a.id_borrow_application;
Do I have to write 4 queries?

You are nesting aggregate function which is not allowed in MySQL.
You don't actually need the sum function for count distinct phone_nos for different conditions. Take the count (distinct outside the case and remove sum function and else clause of the case.
Try this:
select a.id_borrow_application,
count(distinct case when call_type = 0 then c.phone_no end) CVG_CALL_OUT_COUNTS_6M,
count(distinct case when call_type = 0
and c.days <= 30 then c.phone_no end) CVG_CALL_OUT_COUNTS_1M,
count(distinct case when call_type = 1 then c.phone_no end) CVG_CALL_IN_COUNTS_6M,
count(distinct case when call_type = 1
and c.days <= 30 then c.phone_no end) CVG_CALL_IN_COUNTS_1M
from t_snow_borrow_application_id a
join t_snow_call_mobile b
join t_snow_call_record_201612 c on (
a.id_borrow_application = b.id_borrow_application
and b.id = c.id_call_mobile
)
group by a.id_borrow_application;

Related

Slow MySQL queries using SUM()

I have to run two queries in my code to get my tenants balance. However, these queries are too slow.
First query, I get all the tenants and it's unit name:
SELECT t.TenantID
FROM Tenants t
JOIN Units u
ON t.UnitID = u.UnitID
Where t.Prospect = 2
AND t.PropertyID = 8
ORDER
BY CONCAT(Left(Replace(UnitName,'-',''),2),
REPEAT('0', (10-CHAR_LENGTH(UnitName))),
Right(Replace(UnitName,'-',''),
CHAR_LENGTH(Replace(UnitName,'-',''))-2
) )
It returns 500 rows
Then I get the balances in 4 conditions. This query will be inside of first query loop:
Select
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalDebit,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingDebit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalCredit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingCredit
From TenantTransactions
Where TenantID= FirstQuery.TenantID
Am I doing the queries wrong? It's taking like 1 minute to run.
Do this in a single query with GROUP BY.
Try something like this:
SELECT t.TenantID, TotalDebit, HousingDebit, TotalCredit, HousingCredit
FROM Tenants t
JOIN Units u ON t.UnitID = u.UnitID
LEFT JOIN (
Select
TenantID,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalDebit,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingDebit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalCredit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingCredit
From TenantTransactions
Group By TenantID
) sums ON sums.TenantID = t.TenantID
Where t.Prospect = 2
AND t.PropertyID = 8
ORDER
BY CONCAT(Left(Replace(UnitName,'-',''),2),REPEAT('0', (10-CHAR_LENGTH(UnitName))),Right(Replace(UnitName,'-',''),CHAR_LENGTH(Replace(UnitName,'-',''))-2))
The inner query may still run for a while but it will only run once.
Try a compound covering index on TenantTransactions containing these columns: (TenantID, TransactionTypeID, ChargeTypeID, TransactionAmount) to optimize the query with the SUMs in it.
Try a compound index on Tenants with the columns (PropertyID, Prospect) in it.
Here's another way to do it with a subquery. You know, the performance problem might not be database performance, but the back and forth between your database and application server. So that is where a single query will help.
SELECT t.TenantID,
(SELECT SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS TotalDebit,
(SELECT SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS HousingDebit,
(SELECT SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS TotalCredit,
(SELECT SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS HousingCredit
FROM Tenants t
JOIN Units u
ON t.UnitID = u.UnitID
Where t.Prospect = 2
AND t.PropertyID = 8
ORDER
BY CONCAT(Left(Replace(UnitName,'-',''),2),REPEAT('0', (10-CHAR_LENGTH(UnitName))),Right(Replace(UnitName,'-',''),CHAR_LENGTH(Replace(UnitName,'-',''))-2))

aggregating by grouping, not just one record of totals

I have a query below that should be totaling up numbers by CSR agent using their extension. Currently it's returning one line/record for one agent and her extension but it's showing the correct totals for all 15 agents on that one record.
However, what I want is for it to list each agent and their extension with their own respective totals for the day. I'm grouping by extension but it doesn't seem to fix the issue.
Is there something in my query that would stick out as a reason for it not breaking my totals up per extension/agent?
SELECT firstn
, lastn
, extension
, Recieved
, RecievedKnown
, Outbound
, outboundKnown
, Missed
, MissedKnown
, duration
, HOLDTIMESECS
FROM (
SELECT firstn
, lastn
, c.extension
, sum(CASE WHEN LEGTYPE1 = 2 AND ANSWERED = 1 THEN 1 ELSE 0 END) AS Recieved
, sum(case when LEGTYPE1 = 2 and answered = 1 and CALLINGPARTYNO = k.phone_number then 1 ELSE 0 end) as RecievedKnown
, sum(CASE WHEN ANSWERED = 1 AND LEGTYPE1 = 1 then 1 ELSE 0 end) AS Outbound
, sum(case when LEGTYPE1 = 1 and FINALLYCALLEDPARTYNO = k.phone_number then 1 ELSE 0 end) as outboundKnown
, sum(case when Answered = 0 then 1 ELSE 0 end) as Missed
, sum(case when ANSWERED = 0 and CALLINGPARTYNO = k.phone_number then 1 ELSE 0 end) as MissedKnown
, sum(b.duration) as duration
, sum(a.holdtimesecs) as holdtimesecs
FROM ambition.session a
INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
right join jackson_id.users c on a.callingpartyno = c.extension or a.finallycalledpartyno = c.extension
LEFT JOIN ambition.known_numbers k ON a.callingpartyno = k.phone_number
WHERE a.ts >= curdate()
and(a.CALLINGPARTYNO in (select extension from ambition.ambition_users) OR a.finallycalledpartyno IN (select extension from ambition.ambition_users))
) x
group by extension;
Your GROUP BY clause is required inside the subquery. Also I suspect you can avoid the right join by using FROM jackson_id.users c. Also you are usingca left join to ambition.known_numbers k but many of the case expressions rely on a non-null value from that table. Either the join should be an inner join or you need to cater for NULLs from that table in those case expressions.
SELECT
firstn
, lastn
, extension
, Recieved
, RecievedKnown
, Outbound
, outboundKnown
, Missed
, MissedKnown
, duration
, HOLDTIMESECS
FROM (
SELECT
firstn
, lastn
, c.extension
, sum(CASE WHEN LEGTYPE1 = 2 AND ANSWERED = 1 THEN 1 ELSE 0 END) AS Recieved
, sum(case when LEGTYPE1 = 2 and answered = 1 and CALLINGPARTYNO = k.phone_number then 1 ELSE 0 end) as RecievedKnown
, sum(CASE WHEN ANSWERED = 1 AND LEGTYPE1 = 1 then 1 ELSE 0 end) AS Outbound
, sum(case when LEGTYPE1 = 1 and FINALLYCALLEDPARTYNO = k.phone_number then 1 ELSE 0 end) as outboundKnown
, sum(case when Answered = 0 then 1 ELSE 0 end) as Missed
, sum(case when ANSWERED = 0 and CALLINGPARTYNO = k.phone_number then 1 ELSE 0 end) as MissedKnown
, sum(b.duration) as duration
, sum(a.holdtimesecs) as holdtimesecs
FROM jackson_id.users c
INNER JOIN ambition.session a on c.extension = a.callingpartyno or c.extension = a.finallycalledpartyno
INNER JOIN ambition.callsummary b ON a.NOTABLECALLID = b.NOTABLECALLID
LEFT JOIN ambition.known_numbers k ON a.callingpartyno = k.phone_number
WHERE a.ts >= curdate()
AND(a.CALLINGPARTYNO in (select extension from ambition.ambition_users)
OR a.finallycalledpartyno IN (select extension from ambition.ambition_users)
)
GROUP BY
firstn
, lastn
, c.extension
) x
;
Personally I have never been keen on table aliases that rely on sequence (a,b,c ...) as that sequence may not remain steady. Instead, I much prefer first-letter-of-each-word where this is possible. users = u, callsummary = cs, sessions = s, known_numbers = kn etc.

working in mysql but not in db2. SQL State: 42601] DB2 SQL Error: SQLSTATE=42601, SQLERRMC==;sum(day(p.create_dt);CONCAT

Below is my query
select YEAR(p.create_dt) as year,
month(p.create_dt) as month,
p.system as systemName,
p.status as status,
sum(day(p.create_dt) = '01') as count1,
sum(day(p.create_dt) = '02') as count2
from pnm_history p
group by year(p.create_dt),
month(p.create_dt)
order by year(p.create_dt),
month(p.create_dt);
getting error near sum()
Replace the day() calls in MySQL with CASE statements:
SELECT p2.year,
p2.month,
p1.system AS systemName,
p1.status AS status,
p2.count1,
p2.count2
FROM pnm_history p1
INNER JOIN
(
SELECT YEAR(p.create_dt) AS year,
MONTH(p.create_dt) AS month,
SUM(CASE WHEN DAY(p.create_dt) = 1 THEN 1 ELSE 0 END) AS count1,
SUM(CASE WHEN DAY(p.create_dt) = 2 THEN 1 ELSE 0 END) AS count2
FROM pnm_history p
GROUP BY YEAR(p.create_dt),
MONTH(p.create_dt)
) p2
ON YEAR(p1.create_dt) = p2.year AND
MONTH(p1.create_dt) = p2.month
ORDER BY p2.year,
p2.month

How to use user variable as counter with inner join queries that contains GROUP BY statement?

I have 2 tables odds and matches :
matches : has match_id and match_date
odds : has id, timestamp, result, odd_value, user_id, match_id
I had a query that get the following information from those tables for each user:
winnings : the winning bets for each user. (when odds.result = 1)
loses : the lost bets for each user.(when odds.result != 1)
points : the points of each user.(the sum of the odds.odd_value) for each user.
bonus : for each continuous 5 winnings i want to add extra bonus to this variable. (for each user)
How to calculate bonus?
I tried to use this query and I faced a problem : (you can check it here SQL Fiddle)
the calculated bonus are not right for all the users :
first user:(winnings:13, bonus=2).
second user:(winnings:8, bonus=2)bonus here should be 1.
third user:(winnings:14, bonus=3)bonus here should be 2.
why does the query not calculate the bonus correctly?
select d.user_id,
sum(case when d.result = 1 then 1 else 0 end) as winnings,
sum(case when d.result = 2 then 1 else 0 end) as loses,
sum(case when d.result = 1 then d.odd_value else 0 end) as points,
f.bonus
FROM odds d
INNER JOIN
(
SELECT
user_id,SUM(CASE WHEN F1=5 THEN 1 ELSE 0 END) AS bonus
FROM
(
SELECT
user_id,
CASE WHEN result=1 and #counter<5 THEN #counter:=#counter+1 WHEN result=1 and #counter=5 THEN #counter:=1 ELSE #counter:=0 END AS F1
FROM odds o
cross join (SELECT #counter:=0) AS t
INNER JOIN matches mc on mc.match_id = o.match_id
WHERE MONTH(STR_TO_DATE(mc.match_date, '%Y-%m-%d')) = 2 AND
YEAR(STR_TO_DATE(mc.match_date, '%Y-%m-%d')) = 2015 AND
(YEAR(o.timestamp)=2015 AND MONTH(o.timestamp) = 02)
) Temp
group by user_id
)as f on f.user_id = d.user_id
group by d.user_id
I am not sure how your result related to matches table,
you can add back WHERE / INNER JOIN clause if you need.
Here is link to fiddle
and the last iteration according to your comments:
And here is a query:
SET #user:=0;
select d.user_id,
sum(case when d.result = 1 then 1 else 0 end) as winnings,
sum(case when d.result = 2 then 1 else 0 end) as loses,
sum(case when d.result = 1 then d.odd_value else 0 end) as points,
f.bonus
FROM odds d
INNER JOIN
(
SELECT
user_id,SUM(bonus) AS bonus
FROM
(
SELECT
user_id,
CASE WHEN result=1 and #counter<5 AND #user=user_id THEN #counter:=#counter+1
WHEN result=1 and #counter=5 AND #user=user_id THEN #counter:=1
WHEN result=1 and #user<>user_id THEN #counter:=1
ELSE
#counter:=0
END AS F1,
#user:=user_id,
CASE WHEN #counter=5 THEN 1 ELSE 0 END AS bonus
FROM odds o
ORDER BY user_id , match_id
) Temp
group by user_id
)as f on f.user_id = d.user_id
group by d.user_id

how to get SUM() of COUNT() column in MySQL

i have the following query, tried using case statement
SELECT t.inst_id, t.inst_username, tcm.city_name,
SUM(CASE WHEN psb.pms_student_bucket_id IS NULL THEN 1 ELSE 0 END) AS not_assiged,
SUM(CASE WHEN COUNT(psb.pms_student_bucket_id) BETWEEN 1 AND 50 THEN 1 ELSE 0 END) AS '1-50',
SUM(CASE WHEN COUNT(psb.pms_student_bucket_id) > 50 THEN 1 ELSE 0 END) AS ' > 50'
FROM tbl_si_di t
JOIN tbl_city_master tcm ON tcm.city_id = t.city_ref_id
JOIN tbl_si_students tss ON tss.inst_ref_id = t.inst_id
LEFT JOIN pms_student_bucket psb ON psb.user_ref_id = tss.user_ref_id
GROUP BY t.inst_id;
I need SUM of pms_student_bucket_id column when their COUNT is '1-50' and '>50'. Right now this query is saying Invalid use of group function.
How would I SUM on COUNT of "pms_student_bucket_id" equals/between some value in mysql?
you could put it in a subquery
SELECT inst_id, inst_username, city_name,
SUM(pms_student_bucket_id IS NULL ) AS not_assiged,
SUM(num_bucket >=10 AND num_bucket <= 20) AS '10 - 20'
SUM(num_bucket <= 50) AS '1-50',
SUM(num_bucket > 50) AS ' > 50'
FROM
( SELECT t.inst_id, t.inst_username, tcm.city_name,psb.pms_student_bucket_id,
COUNT(psb.pms_student_bucket_id) as num_bucket
FROM tbl_si_di t
JOIN tbl_city_master tcm ON tcm.city_id = t.city_ref_id
JOIN tbl_si_students tss ON tss.inst_ref_id = t.inst_id
LEFT JOIN pms_student_bucket psb ON psb.user_ref_id = tss.user_ref_id
GROUP BY t.inst_id
)t1
GROUP BY inst_id;
note you can use the boolean values returned to do what you want.. aka you don't need a case statement, the boolean value returns a 1 or 0 which can then be summed..