SQL case subquery + subquery > 0 - mysql

i am trying to devide a number with another number. but because there is a chance that the result is 0 i want to make a case saying that if it is 0 then it should be 1 for this ive created this:
(CASE(SELECT COUNT(*)
FROM module_score
WHERE user_id = 40 AND medal_id > 1)
+
(SELECT COUNT(*)
FROM user_has_module_score uhms
WHERE user_id = 40 and medal_id > 1)> 0
THEN 1
ELSE 0 END) as passed_percentage
However i get the following syntax error:
medal_id > 1)> 0 THEN 1 ELSE 0 END) as passed_percentage
FROM system_learningbank.user U
WHERE U.id = 40 GROUP BY U.id
Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'THEN 1 ELSE 0 END) as passed_percentage FROM system_learningbank.user U WH' at line 7
So what is the right syntax if to validate that it is not 0? and in my above example i set the variable to 1 but that should be the actual count of the subqueries
My full sql statement
SELECT
(SELECT
COUNT(*)
FROM
module_score MS
WHERE
user_id = 40) + (SELECT
COUNT(UHMS.score)
FROM
user_has_module_score UHMS
WHERE
UHMS.user_id = 40) / ((SELECT
COUNT(*)
FROM
module_score
WHERE
user_id = 40 AND medal_id > 1) + (SELECT
COUNT(*)
FROM
user_has_module_score uhms
WHERE
user_id = 40 and medal_id > 1) > 0) as passed_percentageas
FROM
system_learningbank.user U
WHERE
U.id = 40
GROUP BY U.id;

You are missing the when:
(CASE WHEN (SELECT COUNT(*) FROM module_score WHERE user_id = 40 AND medal_id > 1) +
(SELECT COUNT(*) FROM user_has_module_score uhms WHERE user_id = 40 and medal_id > 1) > 0
THEN 1 ELSE 0
END) as passed_percentage
MySQL treats booleans as integers, so you can actually write this without the case:
( (SELECT COUNT(*) FROM module_score WHERE user_id = 40 AND medal_id > 1) +
(SELECT COUNT(*) FROM user_has_module_score uhms WHERE user_id = 40 and medal_id > 1) > 0
) as passed_percentage
EDIT:
SELECT (SELECT COUNT(*)
FROM module_score MS
WHERE user_id = 40
) +
(SELECT COUNT(UHMS.score)
FROM user_has_module_score UHMS
WHERE UHMS.user_id = 40
) / ((SELECT COUNT(*)
FROM module_score
WHERE user_id = 40 AND medal_id > 1
) +
(SELECT COUNT(*)
FROM user_has_module_score uhms
WHERE user_id = 40 and medal_id > 1
) > 0
) as passed_percentageas
FROM system_learningbank.user U
WHERE U.id = 40
GROUP BY U.id;
I suspect you want something more like this:
SELECT ((ms.cnt + hms.cnt) /
(case when ms.cnt_m1 + hms.cnt_m2 > 0 then ms.cnt_m1 + hms.cnt_m2 end)
) as passed_percentageas
FROM system_learningbank.user U left join
(select userid, count(*) as cnt, sum(medal_id > 1) as cnt_m1
from module_score
group by user_id
) ms
on ms.user_id = u.user_id left join
(select userid, count(*) as cnt, sum(medal_id > 1) as cnt_m1
from user_has_module_score
group by user_id
) hms
on hms.user_id = u.user_id
WHERE U.id = 40;
However, this still looks suspicious . . . the table names suggest that only one really codes the score you want, the denominator is more restrictive than the numerator, but this structure is basically what you seem to want.
GROUP BY U.id;

Related

Combining several similar queries

How can I combine these three queries into one?
SELECT COUNT(*)
FROM Users
WHERE (SELECT COUNT(*) FROM Posts WHERE Posts.OwnerUserId = Users.Id) < 10;
SELECT COUNT(*)
FROM Users
WHERE (SELECT COUNT(*) FROM Posts WHERE Posts.OwnerUserId = Users.Id) BETWEEN 10 AND 20;
SELECT COUNT(*)
FROM Users
WHERE (SELECT COUNT(*) FROM Posts WHERE Posts.OwnerUserId = Users.Id) > 20;
If I follow you correctly, you can use two levels of aggregation. The following query puts each bucket in a separate row:
select
case
when cnt < 10 then '< 10'
when cnt < 20 then '10-20'
else '> 20'
end as bucket,
count(*) cnt
from (
select count(p.owneruserid) cnt
from users u
left join posts p on p.owneruserid = u.id
group by u.id
) t
group by case
when cnt < 10 then '< 10'
when cnt < 20 then '10-20'
else '> 20'
end
Or you can get all three counts on the same row as follows:
select
sum(case when cnt < 10 then 1 else 0 end) as cnt_less_than_10,
sum(case when cnt >= 10 and cnt < 20 then 1 else 0 end) as cnt_10_to_20,
sum(case when cnt > 20 then 1 else 0 end) as cnt_more_than_20
from (
select count(*) cnt
from users u
inner join posts p on p.owneruserid = u.id
group by u.id
) t

SQL JOIN COUNT then using that count value in where clause

I'm trying to select if a user rating (user.rating) is greater then 6 or if the user has more then 100 transactions (transaction table count). Basically count how many transactions the user has then where (transaction count >= 100 OR user rating >= 6).
SELECT *
FROM `user`
JOIN (SELECT COUNT(*)
FROM transaction
WHERE transaction.user_id=user.id
AND type='L'
AND status='S') AS tcount
WHERE (user.rating >= '6' OR tcount >= '100')
Just another possible answer. I've created simplified schemas to test it, please try it and let me know the result.
SELECT *
FROM user
WHERE user.rating >= 6 OR (SELECT COUNT(*) FROM transaction WHERE user_id = user.id and type = 'L' and status = 'S') >= 100;
Use an alias on COUNT(*)
SELECT *
FROM `user`
JOIN (SELECT user_id, COUNT(*) cnt
FROM transaction
WHERE type='L'
AND status='S'
GROUP BY user_id) AS tcount
ON user.id = tcount.user_id
WHERE (user.rating >= '6' OR tcount.cnt >= '100')
You can write that without the subquery, like this
SELECT u.id
FROM `user` u
JOIN `transaction` t
ON t.user_id=u.id
WHERE t.type = 'L' AND t.status = 'S'
GROUP BY u.id
HAVING sum(case when u.rating >= 6 then 1 end) > 0 OR count(*) >= 100

Sql server errors in query

I am trying to collaborate 3 queries to perform arithmetic operation. The queries are shown in
(SELECT ITEM_ID,ISNULL(SUM(REC_GOOD_QTY),0)
FROM INVENTORY_ITEM
WHERE COMPANY_ID = 1
AND INVENTORY_ITEM.COMPANY_BRANCH_ID = 1
AND INVENTORY_ITEM.INV_ITEM_STATUS = 'Inward'
AND GRN_DATE < CAST('2017-01-10 00:00:00.0' AS DATETIME)
GROUP BY INVENTORY_ITEM.ITEM_ID) -
(SELECT ITEM_ID, SUM ( TOTAL_LITRE )
FROM STOCK_REQUISITION_ITEM B, STOCK_REQUISITION A
WHERE A.ID = B.REQUISITION_ID
AND A.COMPANY_ID = 1
AND A.REQ_FROM_BRANCH_ID = 1
AND A.REQUISITION_DATE < CAST('2017-01-10 00:00:00.0' AS DATETIME)
GROUP BY B.ITEM_ID) +
(SELECT ITEM_ID, SUM ( RETURN_QUANTITY )
FROM STOCK_RETURN_ITEM B, STOCK_RETURN A
WHERE A.ID = B.STOCK_RETURN_ID
AND A.COMPANY_ID = 1
AND A.COMPANY_BRANCH_ID = 1
AND A.RETURN_DATE <= CAST('2017-01-10 00:00:00.0' AS DATETIME)
GROUP BY B.ITEM_ID)
I am getting this error.
[Err] 42000 - [SQL Server]Incorrect syntax near '-'.
42000 - [SQL Server]Incorrect syntax near '+'
Not much to go on here for details. And we aren't actually sure if you are using mysql or sql server but pretty sure you are using sql server. I think you can accomplish what you are trying to do with something along these lines.
with Iventory as
(
SELECT i.ITEM_ID
, GoodQty = ISNULL(SUM(i.REC_GOOD_QTY), 0)
FROM INVENTORY_ITEM i
WHERE COMPANY_ID = 1
AND i.COMPANY_BRANCH_ID = 1
AND i.INV_ITEM_STATUS = 'Inward'
AND i.GRN_DATE < '2017-01-10'
GROUP BY i.ITEM_ID
)
, StockRequisition as
(
SELECT ITEM_ID
, TotalLitre = SUM(TOTAL_LITRE)
FROM STOCK_REQUISITION_ITEM B
JOIN STOCK_REQUISITION A ON A.ID = B.REQUISITION_ID
WHERE A.COMPANY_ID = 1
AND A.REQ_FROM_BRANCH_ID = 1
AND A.REQUISITION_DATE < '2017-01-10'
GROUP BY B.ITEM_ID
)
StockReturn as
(
SELECT ITEM_ID
, ReturnQuantity = SUM(RETURN_QUANTITY)
FROM STOCK_RETURN_ITEM B
JOIN STOCK_RETURN A ON A.ID = B.STOCK_RETURN_ID
WHERE A.COMPANY_ID = 1
AND A.COMPANY_BRANCH_ID = 1
AND A.RETURN_DATE <= '2017-01-10'
GROUP BY B.ITEM_ID
)
select i.ITEM_ID
, MyCalculation = i.GoodQty - isnull(Req.TotalLitre, 0) + isnull(sr.ReturnQuantity, 0)
from Inventory i
left join StockRequisition sr on sr.ITEM_ID = i.ITEM_ID
left join StockReturn Req on Req.ITEM_ID = i.ITEM_ID
In your queries you always returns two fields ITEM_ID and a numeric field.
To apply an arithmetical operation you must return one numeric field
The first query:
SELECT ITEM_ID,ISNULL(SUM(REC_GOOD_QTY),0)
becomes
SELECT ISNULL(SUM(REC_GOOD_QTY),0)
The second query:
SELECT ITEM_ID, SUM ( TOTAL_LITRE )
becomes
SELECT SUM ( TOTAL_LITRE )
The third query:
SELECT ITEM_ID, SUM ( RETURN_QUANTITY )
becomes
SELECT SUM ( RETURN_QUANTITY )
So the GROUP BY returns more than one row per query
UPDATE
i try to rewrite your query:
SELECT DISTINCT ii.item_id,
ISNULL(
(SELECT SUM(ii2.rec_good_qty)
FROM inventory_item ii2
WHERE ii2.item_id = ii.item_id
AND ii.company_id = 1
AND ii.company_branch_id = 1
AND ii.inv_item_status = 'Inward'
AND ii.grn_date < CAST('2017-01-10 00:00:00.0' AS DATETIME))
,0) -
ISNULL(
(SELECT SUM(total_litre)
FROM stock_requisition_item b
JOIN stock_requisition a
ON a.id = b.requisition_id
WHERE a.company_id = 1
AND a.req_from_branch_id = 1
AND a.requisition_date < CAST('2017-01-10 00:00:00.0' AS DATETIME))
,0) +
ISNULL(
(SELECT SUM(return_quantity)
FROM stock_return_item b
JOIN stock_return a
ON a.id = b.stock_return_id
WHERE a.company_id = 1
AND a.company_branch_id = 1
AND a.return_date <= CAST('2017-01-10 00:00:00.0' AS DATETIME))
,0) AS result
FROM inventory_item ii
WHERE ii.company_id = 1
AND ii.company_branch_id = 1
AND ii.inv_item_status = 'Inward'
AND ii.grn_date < CAST('2017-01-10 00:00:00.0' AS DATETIME)

Operand should contain 1 column(s) - in mysql query

I have the following complex query that is giving me an error
Operand should contain 1 column(s)
Can anyone suggest what is wrong
SELECT
t.user_id AS user_id,
t.organisation_id AS organisation_id,
t.firstname AS firstname,
t.surname AS surname,
t.username AS username,
t.year_id AS year_id,
t.form_name AS form_name,
t.House AS House,
rcPoints.total AS milestoneRedeemedCodesTotal,
rcFilteredPoints.total AS redeemedCodesTotalFiltered,
(
COALESCE (rcFilteredPoints.total, 0) - COALESCE (milestoneHistory.total, 0)
) AS redeemedCodesTotalAvailableFiltered,
ABS(
FLOOR(
(
COALESCE (rcFilteredPoints.total, 0) - COALESCE (milestoneHistory.total, 0)
) / 1000
) * 1000
) AS redeemedCodesTotalTowardsMilestone,
ABS(
FLOOR(
(
COALESCE (rcFilteredPoints.total, 0) - COALESCE (milestoneHistory.total, 0)
) / 1000
)
) AS redeemedCodesMilestoneTriggers,
COALESCE (milestoneHistory.total, 0) AS historyTotal
FROM
`myuser` `t`
LEFT JOIN (
SELECT
rc.user_id AS user_id,
SUM(rc.school_points) AS total
FROM
`redeemed_codes` `rc`
INNER JOIN myuser m ON (m.user_id = rc.user_id)
WHERE
(rc.date_redeemed >= 0)
AND (m.organisation_id = 58022)
GROUP BY
rc.user_id
) AS rcPoints ON (rcPoints.user_id = t.user_id)
LEFT JOIN (
SELECT
rc.user_id AS user_id,
SUM(rc.school_points) AS total
FROM
`redeemed_codes` `rc`
INNER JOIN myuser m ON (m.user_id = rc.user_id)
WHERE
(rc.date_redeemed >= 0)
AND (m.organisation_id = 58022)
GROUP BY
rc.user_id
) AS rcFilteredPoints ON (
rcFilteredPoints.user_id = t.user_id
)
LEFT JOIN (
SELECT
mh.user_id AS user_id,
mh.milestone_id AS milestone_id,
MAX(mh.points_when_triggered) AS total
FROM
`milestone_history` `mh`
WHERE
mh.milestone_id = 13
GROUP BY
mh.user_id
) AS milestoneHistory ON (
milestoneHistory.user_id = t.user_id
)
WHERE
(
(
SELECT
COALESCE (count(*), 0)
FROM
milestone_history mha
WHERE
mha.milestone_id = 13
AND mha.user_id = t.user_id
) = 0
)
AND (t.organisation_id = 58022)
AND
(
SELECT * FROM
redeemed_codes t1
WHERE
organisation_id = 1
AND
(
SELECT
sum(school_points)
FROM
redeemed_codes t2
WHERE
t2.redeemed_code_id <= t1.redeemed_code_id
) >= 1000
ORDER BY redeemed_code_id
LIMIT 1
)
GROUP BY
t.user_id
ORDER BY
redeemedCodesMilestoneTriggers DESC
LIMIT 1
Your query might have multiple errors, but this condition in the WHERE clause is definitely suspect and would lead to that error:
AND (SELECT *
FROM redeemed_codes t1
WHERE organisation_id = 1 AND
(SELECT sum(school_points)
FROM redeemed_codes t2
WHERE t2.redeemed_code_id <= t1.redeemed_code_id
) >= 1000
ORDER BY redeemed_code_id
LIMIT 1
)
I have no idea what you are trying to do. Sometimes, the solution is simply EXISTS:
EXISTS (SELECT *
FROM redeemed_codes t1
WHERE organisation_id = 1 AND
(SELECT sum(school_points)
FROM redeemed_codes t2
WHERE t2.redeemed_code_id <= t1.redeemed_code_id
) >= 1000
)

Can't access column pick_country_iso

I have this query
SELECT pick_up_id, (select pick_name from pick_up_point where pick_up_point.pick_up_id = s.pick_up_id limit 1) as pick_name, total_boxes, (SUM(r_occupied) + SUM(s_occupied)) AS total_occupied, (total_boxes - (SUM(r_occupied) + SUM(s_occupied))) as free_boxes, round(((SUM(r_occupied) + SUM(s_occupied)) / total_boxes * 100),2) as pct_usage,(select pick_country_iso from pick_up_point where pick_up_point.pick_up_id = s.pick_up_id limit 1) as pick_country_iso
FROM(
SELECT p.r_pick_up_id AS pick_up_id, COUNT(p.parcel_id) AS r_occupied, 0 AS s_occupied,
(SELECT COUNT(rl.lookup_id) FROM racks r INNER JOIN rack_lookup rl ON rl.rack_type = r.rack_type WHERE r.pick_up_id = p.r_pick_up_id) AS total_boxes
FROM v_last_parcel_event p
WHERE p.event_type IN (2,3,6,8,16,18,26,27,101,102,104,105,107,112,122,124,127,151,152,153)
AND p.box_size <= 3 AND IFNULL(p.overflow_parcel, 0) = 0
AND p.r_pick_up_id IS NOT NULL
GROUP BY p.r_pick_up_id
UNION ALL
SELECT p.s_pick_up_id AS pick_up_id, 0 AS r_occupied, COUNT(p.parcel_id) AS s_occupied,
(SELECT COUNT(rl.lookup_id) FROM racks r INNER JOIN rack_lookup rl ON rl.rack_type = r.rack_type WHERE r.pick_up_id = p.s_pick_up_id) AS total_boxes
FROM v_last_parcel_event p
WHERE p.event_type IN (2,6,8,12,16,18,26,27,101,102,104,105,107,112,122,124,151,152,153)
AND p.box_size <= 3 AND IFNULL(p.overflow_parcel, 0) = 0
AND p.s_pick_up_id IS NOT NULL
GROUP BY p.s_pick_up_id
) as s
GROUP BY s.pick_up_id;
On above query on first line, i'm getting column pick_country_iso
(select pick_country_iso from pick_up_point where pick_up_point.pick_up_id = s.pick_up_id limit 1) as pick_country_iso
The result is in following image.
Now i'm trying to add a where clause in the above query at the end
as s WHERE pick_country_iso="ABC"
GROUP BY s.pick_up_id;
but I'm getting this error #1054 - Unknown column 'pick_country_iso' in 'where clause'.
Thank you for any help.