Reputation: 700
I'm trying to calculate the the percentage of items sent by royal mail from the delivery table.
(SELECT post_method
FROM delivery_tbl
WHERE post_method = 'RM')
/
SELECT post_method
FROM delivery_tbl;
I get an error saying
"SQL command not properly ended".
Any help on this would be great! Thanks!
Upvotes: 3
Views: 8625
Reputation: 14189
You are doing a division of 2 queries, but to properly display the result, you need to add a SELECT
statement of the division.
This is wrong:
-- Result: SQL command not properly ended
(SELECT 100 FROM DUAL) / (SELECT 50 FROM DUAL)
This is OK:
-- Result: 2
SELECT
(SELECT 100 FROM DUAL) / (SELECT 50 FROM DUAL)
FROM
DUAL
You should also try to add column names so it's clearer:
-- ResultOfDivision: 2
SELECT
(SELECT 100 FROM DUAL) / (SELECT 50 FROM DUAL) ResultOfDivision
FROM
DUAL
Please keep in mind that when doing these type of divisions (or any arithmetic operation) between subqueries, each subquery must return 1 row. If they don't then the SQL engine wouldn't know which row to use and throws an error.
-- Result: single-row subquery returns more than one row.
SELECT
(SELECT 100 FROM DUAL) / (SELECT SomeColumn FROM YourTableWithManyRows) ResultOfDivision
FROM
DUAL
For this last example, the correct expression would be the following (for each row).
SELECT
(100 / SomeColumn) ResultOfDivision
FROM
YourTable
WHERE
SomeColumn <> 0 -- Prevent division by 0!!
For your case, seems that you are trying to see the following:
-- Make sure SELECT COUNT(1) FROM delivery_tbl isnt 0!
SELECT
post_method,
COUNT(post_method) * 100 / (SELECT COUNT(1) FROM delivery_tbl) 100perc, -- 100 based percentage
COUNT(post_method) / (SELECT COUNT(1) FROM delivery_tbl) 1perc -- 1 based percentage
FROM
delivery_tbl
GROUP BY
post_method
Upvotes: 2
Reputation: 23578
You can do this using conditional aggregation, like so:
SELECT round (100 * (count(case when post_method = 'RM' then 1 end) / count(*)), 2) royal_mail_items_percentage
FROM delivery_tbl;
I've included the round
function as it looks like you only want to display up to 2 decimal places.
Doing the query using conditional aggregation means you only have to query the table once, so it should be more performant than the other answers, which need to hit the table more than once.
Upvotes: 4
Reputation: 11
Use the sql:
select (
(select sum(post_method) from delivery_tbl where post_method = 'RM') /
(select sum(post_method) from delivery_tbl)) * 100 as "royalperc" from dual ;
Upvotes: 0
Reputation: 1473
SELECT ((SELECT post_method FROM delivery_tbl Where post_method = 'RM')/ (SELECT post_method FROM delivery_tbl))*100 as royalperc
Updated query to get counts instead
SELECT ((SELECT COUNT(post_method) FROM delivery_tbl Where post_method = 'RM')/ (SELECT COUNT(post_method) FROM delivery_tbl))*100 as royalperc
I believe you should use the second query
Upvotes: 1
Reputation: 436
Add a SELECT statement at the beginning:
SELECT ((SELECT post_method FROM delivery_tbl Where post_method = 'RM') / (SELECT post_method FROM delivery_tbl));
Upvotes: 0
Reputation: 4309
Select post_method, (Count(post_method)* 100 / (Select Count(*) From
delivery_tbl)) as percentage
From delivery_tbl
Where post_method = 'RM'
Group By post_method
Upvotes: 4