Getting invalid use of group function in update query - mysql

Can Someone please help me where is the issue
am getting 'invalid use of group function' in below query
UPDATE t1
JOIN t2 ON t1.id=t2.id
SET t1.total_amount = SUM(IF((t2.`due` <= 0), t2.`amount`, 0))
WHERE t2.flag=1 AND t2.id=003;

You want to aggregate in a subquery, then join and set in the outer query:
update t1
inner join (
select id, sum(case when due < 0 then t2.amount else 0 end) total_amount
from t2
where id = 3 and flag = 1
group by id
) t2 on t1.id = t2.id
set t1.total_amount = t2.total_amount

Related

How to use 'group by' while having a sub query in MySQL?

I have the following query:
SELECT c.text1, sum(c.num1), sum(c.num2), sum(c.num3),
(SELECT count(id) FROM table2 WHERE type = 1 AND txt = c.text1 AND spec_id = c.sp_id)
FROM table1 as c
WHERE c.type = 1
GROUP BY c.text1, c.sp_id
Is there a workaround to loose the c.sp_id from the GroupBy clause somehow? I know that if I remove it MySQL will return an error.
Or is there a way to group the results of this query by c.text1 only?
If I understand the problem correctly, you need to do two separate aggregations. This is one version of the query:
SELECT c.text1, c.sum1, c.sum2, c.sum3, t2.cnt
FROM (SELECT c.text1, sum(c.num1) as sum1, sum(c.num2) as cum2, sum(c.num3) as sum3
FROM table1 c
GROUP BY c.text1
) c LEFT JOIN
(SELECT txt, count(*) as cnt
FROM table2 t2
WHERE t2.type = 1 AND
EXISTS (SELECT 1
FROM table1 c2
WHERE t.txt = c2.txt AND c2.type = 1 AND
t.spec_id = c2.sp_id
)
) t2
ON t2.txt = c.text1
WHERE c.type = 1;

How to do while loop with if exist in SQL Server stored procedure?

I'm just learning to use while loop in stored procedure I'm not sure why the stored procedure does not return any value.
I'm using the if exist to check whether the id exist in the table or not.
And if there is more than 1 id I need to execute again the same query.
I tried using while loop and its not working.
I declare the #keyValue as Varchar and it causes an error
Conversion failed when converting the varchar value 'c29dc109b310479fa5c281eb20c61656' to data type int.
That is why I use COUNT at the WHILE
IF EXISTS (SELECT t1.ref_id
FROM pbosproinvoiceitem t1
WHERE t1.ref_id = #keyValue)
WHILE COUNT(#keyValue) > 1
BEGIN
--need to do for loop
SELECT #balWghtSso = (SELECT t1.act_wght
FROM ccossoitem t1
WHERE t1.master_id = #keyValue) -
(SELECT t1.wght
FROM ccossoitem t1
WHERE t1.master_id = #keyValue)
SELECT #balWghtBl = (SELECT t1.act_wght
FROM ccosblitem t1
WHERE t1.master_id = #keyValue) -
(SELECT t1.wght
FROM ccosblitem t1
WHERE t1.master_id = #keyValue)
SELECT DISTINCT
t1.debtor_code AS customer_code, t1.tml_code, t1.scn,
t2.cg_type, t3.qty, #balWghtSso AS mea, t3.vol,
CASE
WHEN t3.from_loc = 'DL' THEN 1 ELSE 0
END AS ex_wharf,
t2.dg_flg, 0 AS conveyor_ind, t1.sso_num AS ref_doc_num,
t1.id AS ref_id
FROM
ccosso t1
INNER JOIN
ccossoitem t2 ON t1.id = t2.master_id
INNER JOIN
ccosgodown t3 ON t3.blso_id = t1.id AND t3.blso_item_id = t2.id
WHERE
t3.move_type = 'LOAD'
AND t1.id = #keyValue
UNION ALL
SELECT DISTINCT
t1.debtor_code AS customer_code, t1.tml_code, t1.scn,
t2.cg_type, t3.qty,
#balWghtBl AS mea, t3.vol,
CASE
WHEN t3.from_loc = 'DD' THEN 1 ELSE 0
END AS ex_wharf,
t2.dg_flg, 0 AS conveyor_ind, t1.bl_num AS ref_doc_num,
t1.id AS ref_id
FROM
ccosbl t1
INNER JOIN
ccosblitem t2 ON t1.id = t2.master_id
INNER JOIN
ccosgodown t3 ON t3.blso_id = t1.id AND t3.blso_item_id = t2.id
WHERE
t3.move_type = 'DELV'
AND t1.id = #keyValue
END;
You have to re-write your while loop like below, and remove the IF exists condition.
WHILE( SELECT COUNT(1)
FROM pbosproinvoiceitem t1
WHERE t1.ref_id = #keyValue > 1)

Getting error "Operand should contain 1 column(s)" on this query

So I have the code below:
SELECT student_name FROM student S WHERE S.student_id IN
(SELECT t1.student_id, SUM(IF(t2.test_date IS NULL, 0, 1)) AS increase_score
FROM
test t1
LEFT JOIN test t2
ON t1.student_id = t2.student_id
AND t1.test_date < t2.test_date
AND t1.Score <= t2.Score
GROUP BY t1.student_id
HAVING
increase_score = 0
AND count(*) > 1)
I am getting an error "Operand should contain 1 column(s)". This only arises after adding the outer SELECT statement. I have confirmed the inner query is working as intended otherwise. I've looked at some other examples involving the same error, but I have not been able to determine what to do to fix it in this case.
The error is quite clear : you can't have more than one field in your sub query, you're macthing a field against a single column, obviously.
So just move the SUM in the HAVING clause :
SELECT student_name
FROM student S
WHERE S.student_id IN
(SELECT t1.student_id
FROM test t1
LEFT JOIN test t2
ON t1.Name = t2.Name
AND t1.Date < t2.Date
AND t1.Score <= t2.Score
GROUP BY t1.Name
HAVING
SUM(IF(t2.test_date IS NULL, 0, 1)) = 0
AND count(*) > 1)
http://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
A query used as an argument to the in operator must return a single column. One way to rework this query is to remove the sum in the select list, and keep it only in the having clause:
SELECT student_name
FROM student
WHERE student_id IN (SELECT t1.student_id
FROM test t1
LEFT JOIN test t2 ON t1.Name = t2.Name AND
t1.Date < t2.Date AND
t1.Score <= t2.Score
GROUP BY t1.Name
HAVING SUM(IF(t2.test_date IS NULL, 0, 1)) = 0 AND
COUNT(*) > 1
)

How to count and get result of two rows in Mysql Select Query?

This is my table structure.
sometime table1 data my repeat (Ex : Actually Id 1 should have only 4 rows but sometime it is 8 due to duplication) so avoid duplication I use GROUP BY command in select query
Table 1
|id| website|time|
-----------------
|01|facebook|20.0|
|01|google |40.0|
|01|youtube |10.0|
|01|ebay |30.0|
|02|facebook|50.0|
|02|ebay |50.0|
Table 2
|id|marks|
-----------
|01| 80|
|02| 90|
|03| 70|
|04| 100|
I want to select (marks),(time on facebook) and (count of time on google & youtube) of specific user
Following select query gives (marks),(time on facebook) of user id '01'
How to receive count of time of both google and youtube of id'1' in same query ?
SELECT table2.id,table2.marks, table1.time
FROM table1
RIGHT JOIN table2 ON table1.id= table2.id
WHERE table1.website LIKE ('%facebook%')
AND table1.id= '01'
GROUP BY table1.id, table1.website
You want to find the time on facebook and then the sum of youtube and google for a particular user you can use the mysql conditional sum to achieve it
select
sum(case when t1.website = 'facebook' then t1.time else 0 end) as `fb_time`,
(
sum(case when t1.website='google' then t1.time else 0 end)+
sum(case when t1.website='youtube' then t1.time else 0 end)
)
as `google_youtube`,
t2.marks
from table1 t1
join table2 t2 on t1.id = t2.id
where t1.id = '01'
If you need to calculate the same for all the users then you can do it as
select
t1.id,
sum(case when t1.website = 'facebook' then t1.time else 0 end) as `fb_time`,
(
sum(case when t1.website='google' then t1.time else 0 end)+
sum(case when t1.website='youtube' then t1.time else 0 end)
)
as `google_youtube`,
t2.marks
from table1 t1
join table2 t2 on t1.id = t2.id
group by t1.id
If I understand your query correctly, I think you will need to use a subquery.
The following subquery returns two counts; time_on_facebook & time_on_google_and_youtube
for all users
SELECT t1.id, t2.marks,
COUNT(t1.time) as time_on_facebook,
(SELECT COUNT(t1_sq.time)
FROM `table1` as t1_sq
WHERE (t1_sq.website = "youtube" OR t1_sq.website = "google")
AND t1_sq.id = t1.id
GROUP BY t1.id) as time_on_google_and_youtube
FROM `table1` as t1
LEFT JOIN table2 t2 ON t2.id = t1.id
WHERE t1.website = "facebook"
GROUP BY t1.id
To restrict it to user id = 01, add in a WHERE clause
SELECT t1.id, t2.marks,
COUNT(t1.time) as time_on_facebook,
(SELECT COUNT(t1_sq.time)
FROM `table1` as t1_sq
WHERE (t1_sq.website = "youtube" OR t1_sq.website = "google")
AND t1_sq.id = t1.id
GROUP BY t1.id) as time_on_google_and_youtube
FROM `table1` as t1
LEFT JOIN table2 t2 ON t2.id = t1.id
WHERE t1.website = "facebook" AND t1.id = 1
GROUP BY t1.id
Are you sure you want COUNT(time) or do you want SUM(time)?
Lastly, consider adding a primary key to both tables and maybe rename the "id" column to "user_id" for clarity.
Its not clear what you want the output to look like. I made a query,
but did not try it. Try it and let me know if it works.
select t1.id, t1.website, sum(t1.time) as total_time, max(t2.marks) as marks
from table1 as t1
left join table2 as t2
on t1.id = t2.id
where t1.website = 'facebook'
and t1.id = '01'
group by t1.id, t1.website
UNION
select t1.id, t1.website, sum(t1.time) as total_time, max(t2.marks) as marks
from table1 as t1
left join table2 as t2
on t1.id = t2.id
where t1.website IN ('youtube', 'google')
and t1.id= '01'
group by t1.id, t1.website

Return 0 if no row/empty result in mysql

is there a way where I can return 0 if i get an empty result in mysql?
SELECT t1.amount as Amt
FROM table1 as t1
INNER JOIN table2 as t2
ON t1.project_id = t2.id
WHERE t2.proj_name = "Project_Kalinga"
AND t1.date_sent = (SELECT MAX(date_sent) FROM table WHERE project_id = "0123")
Currently for the project name 'Project Kalinga' I get an empty result.
Is there a way where from this query even if i get an empty result, I'll just get 0 instead?
So then the output would be like
| Amt |
| 0 |
Thank You!
Here's the sqlfiddle
http://sqlfiddle.com/#!2/0c4c5/2
You can
create a "Dummy row" with zero
do a left join to your main query.
Coalesce the real value and the dummy value
SELECT Coalesce(t1.amt, d.amount) AS amt
FROM (SELECT 0 as amount
FROM DUAL) AS d
LEFT JOIN
(SELECT t1.amount AS Amt
FROM table1 AS t1
INNER JOIN table2 AS t2
ON t1.project_id = t2.id
WHERE t2.proj_name = "project_kalinga"
AND t1.date_sent = (SELECT Max(date_sent)
FROM table1
WHERE project_id = "0123")) AS t1
ON 1 = 1
Demo
Try this:
SELECT IFNULL(t1.amount,0) as Amt
FROM table t1
LEFT OUTER JOIN table2 t2
ON t1.project_id = t2.id AND t2.proj_name = "Project_Kalinga"
WHERE t1.date_sent = (SELECT MAX(date_sent) FROM table WHERE project_id = "0123")