Divide one table by another table created in the same query - mysql

I have the following SQL query:
SELECT `NeighbourhoodName`,
count(NAME) as `Number of Parks`,
sum(CASE
WHEN `parks`.`Advisories` = 'Y' THEN 1
ELSE 0
END) as Advisories,
FROM parks
GROUP BY `NeighbourhoodName`;
In the second line of the code, I create a column called "Number of Parks". I would like all the values in the next column (Advisories) to be divided by the values in "Number of parks". However, when I try to insert the division statement after the column like this:
SELECT `NeighbourhoodName`,
count(NAME) as `Number of Parks`,
sum(CASE
WHEN `parks`.`Advisories` = 'Y' THEN 1
ELSE 0
END)/`Number of Parks` as Advisories
FROM parks
GROUP BY `NeighbourhoodName`;
I get the following error:
Unknown column, `Number of Parks` in field list.
How can I perform this division while still keeping it in one query?

You need to use an outer query to do the division.
SELECT `NeighbourhoodName`,
`Number of Parks`,
Advisories/`Number of Parks` as Advisories
FROM ( SELECT `NeighbourhoodName`,
count(NAME) as `Number of Parks`,
sum( CASE WHEN `parks`.`Advisories` = 'Y' THEN 1 ELSE 0 END ) as Advisories
FROM parks
GROUP BY `NeighbourhoodName`
) as tbl;
Problems with Column Aliases
An alias can be used in a query select list to give a column a
different name. You can use the alias in GROUP BY, ORDER BY, or HAVING
clauses to refer to the column.

Or use the expression of count(Name) instead of Number of Parks:
select NeighbourhoodName,
count(Name) as `Number of Parks`,
sum(case when Advisories='Y' then 1 else 0 end)
/count(Name) as Advisories
from parks
group by NeighbourhoodName;

Related

Need help DB Query for this scenario

I am unable to derive a SQL query for the following table content.
When i tried below query i am getting above said output. Can someone help me to give the required query for it.
select Name, count(Status) from mytable where Status='Open' group by mytable union
select Name, count(Status) from mytable where Status='Cleared' group by mytable
Use case expressions in the select list to do conditional aggregation.
select Name,
count(case when Status = 'Open' then 1 end) as opencnt,
count(case when Status = 'Cleared' then 1 end) as clearedcnt
from mytable
where Status in ('Open', 'Cleared')
group by Name
COUNT() counts non-null values. The case expressions above returns null when the conditions aren't fulfilled.

req_type wise count id in one query

I have an sql query problem . I don't want to execute three times query for same result.
In my table I have one field req_type which have three parameter ,
either 1, either 2, either 3 .
I want counter based on req_type in one query instead of by executing query 3 times like below
select count(id) as premium FROM tablename where req_type=1
select count(id) as premium1 FROm tablename where req_type=2
select count(id) as premium2 FROm tablename where req_type=3
I am stuck , can anybody help me?
You could use case for such type of count
select sum(case when req_type=1 then 1 else 0 end) as premium,
sum(case when req_type=2 then 1 else 0 end) as premium1,
sum(case when req_type=3 then 1 else 0 end) as premium2
FROM tablename
Use one query instead of threes by using group by cluase
select req_type , count(id) as premium
FROM tablename
where req_type in (1,2,3)
group by req_type
Use a GROUP BY
SELECT req_type, COUNT(id) AS count_premium
FROM tablename
GROUP BY req_type;

SQL Union query error

Im trying to join two count querys
SELECT COUNT(*) AS total FROM clients WHERE addedby = 1
UNION
SELECT COUNT(*) AS converts FROM clients WHERE addedby = 1 AND status = '6'
What this returns is
total
4
0
this is the correct data, what I was expecting was this
total converts
4 0
You don't need a UNION query to do this. SELECT A UNION SELECT B returns the rows of A followed by the rows of B (deduplicated; if you want all rows from both datasets, use UNION ALL).
What you want is something like this:
select
(select count(*) from clients where addedby=1) as total,
(select count(*) from clients where addedby=1 and status='6') as converts
Other way to do this is using a case ... end expression that returns 1 if status='6':
select
count(*) from clients,
sum(case when status='6' then 1 else 0 end) as converts
from clients
No UNION needed, do it in one pass.
SELECT COUNT(*) as total,
SUM(CASE status WHEN '6' THEN 1 ELSE 0 END) as converts
FROM clients;
The simplest way to write this query is as a conditional aggregation:
select count(*) as total, sum(status = '6') as converts
from cleints
where addedby = 1;
MySQL treats booleans as integers with 1 being true and 0 being false. You can just sum of the values to get a count.

Using sum() to mimic count() of rows

I want to count the number of rows where a particular field = 'Q1'.
I usually use count(particular_field), but this does not allow me to count only when that field = 'Q1'.
Does the query SUM(particular_field = 'Q1') work for this matter? Or am I able to do count(particular_field = 'Q1')?
you can either do
select count(*)
from table
where particular_field = 'Q1'
or
select sum(case when particular_field ='Q1' then 1 else 0 end)
from table
You should be able to use a CASE statement with your SUM() (See SQL Fiddle)
SELECT SUM(CASE WHEN particular_field = 'Q1' THEN 1 ELSE 0 END) yourCount
FROM yourTable
Or (See SQL Fiddle) - this will give you a list of the count and each field. If you only want the one value, then use a WHERE clause to filter:
select count(*), particular_field
from yourTable
group by particular_field

error : #1242 - Subquery returns more than 1 row

I got an error: #1242 - Subquery returns more than 1 row when i run this sql.
CREATE VIEW test
AS
SELECT cc_name,
COUNT() AS total,
(SELECT COUNT(*)
FROM bed
WHERE respatient_id > 0
GROUP BY cc_name) AS occupied_beds,
(SELECT COUNT(*)
FROM bed
WHERE respatient_id IS NULL
GROUP BY cc_name) AS free_beds
FROM bed
GROUP BY cc_name;
The problem is that your subselects are returning more than one value - IE:
SELECT ...
(SELECT COUNT(*)
FROM bed
WHERE respatient_id IS NULL
GROUP BY cc_name) AS free_beds,
...
...will return a row for each cc_name, but SQL doesn't support compacting the resultset for the subselect - hence the error.
Don't need the subselects, this can be done using a single pass over the table using:
SELECT b.cc_name,
COUNT(*) AS total,
SUM(CASE
WHEN b.respatient_id > 0 THEN 1
ELSE 0
END) AS occupied_beds,
SUM(CASE
WHEN b.respatient_id IS NULL THEN 1
ELSE 0
END) AS free_beds
FROM bed b
GROUP BY b.cc_name
This is because your subqueries (the SELECT bits that are inside parentheses) are returning multiple rows for each outer row. The problem is with the GROUP BY; if you want to use subqueries for this, then you need to correlate them to the outer query, by specifying that they refer to the same cc_name as the outer query:
CREATE VIEW test
AS
SELECT cc_name,
COUNT() AS total,
(SELECT COUNT()
FROM bed
WHERE cc_name = bed_outer.cc_name
AND respatient_id > 0) AS occupied_beds,
(SELECT COUNT(*)
FROM bed
WHERE cc_name = bed_outer.cc_name
WHERE respatient_id IS NULL) AS free_beds
FROM bed AS bed_outer
GROUP BY cc_name;
(See http://en.wikipedia.org/wiki/Correlated_subquery for information about correlated subqueries.)
But, as OMG Ponies and a1ex07 say, you don't actually need to use subqueries for this if you don't want to.
Your subqueries return more than 1 row. I think you you need something like :
SELECT COUNT(*) AS total,
COUNT(CASE WHEN respatient_id > 0 THEN 1 END) AS occupied_beds,
COUNT(CASE WHEN respatient_id IS NULL THEN 1 END) AS free_beds
FROM bed
GROUP BY cc_name
You can also try to use WITH ROLLUP + pivoting (mostly for learning purposes, it's a much longer query ) :
SELECT cc_name,
MAX(CASE
WHEN num_1 = 1 THEN tot_num END) AS free_beds,
MAX(CASE
WHEN num_1 = 2 THEN tot_num END) AS occupied_beds,
MAX(CASE
WHEN num_1 = IS NULL THEN tot_num END) AS total
FROM
(SELECT cc_name, CASE
WHEN respatient_id > 0 THEN 1
WHEN respatient_id IS NULL THEN 2
ELSE 3 END as num_1,
COUNT(*) as tot_num
FROM bed
WHERE
CASE
WHEN respatient_id > 0 THEN 1
WHEN respatient_id IS NULL THEN 2
ELSE 3 END != 3
GROUP BY cc_name,
num_1 WITH ROLLUP)A
GROUP BY cc_name
SELECT COUNT()
FROM bed
WHERE respatient_id > 0
GROUP BY cc_name
You need to remove the group-by in the sub query, so possibly something like
SELECT COUNT(*)
FROM bed
WHERE respatient_id > 0
or possibly -- depending on what your application logic is....
SELECT COUNT(*) from (
select count(*),cc_name FROM bed
WHERE respatient_id > 0
GROUP BY cc_name) filterview