I'm taking a SQL class and I need help with a question.
I have the following table on a phpmyadmin server
patient (id, age)
with a total of 100 patients
I'm told to find the sum of people that have same age using SQL.
I wrote this query:
SELECT COUNT(age)
FROM patient
HAVING (COUNT(age) > 1);
but it returns 100 as a result and when I did this query and found the number of patients who have the same age for each age and calculated the count manually I found 78 and I checked it manually and it's indeed 78.
SELECT COUNT(*)
FROM patient
GROUP BY age
HAVING (COUNT(*) > 1);
What's wrong with my code?
Start with a subquery that gets the counts of people with each age. Then filter this to counts more than 1 so it's just people with the same age.
Then in the main query you use SUM() to add all these counts together, to get the total number of patients.
SELECT SUM(count)
FROM (
SELECT COUNT(*) AS count
FROM patient
GROUP BY age
HAVING count > 1
) AS x
select age, count(*) from patient group by age;
Related
This is my persons table:
neighborhood birthyear
a 1958
a 1959
b 1970
c 1980
I'd like to get the COUNT of people in an age group within every neighborhood. For example, if I wanted to get everyone under the age of 18, I would get:
neighborhood count
a 0
b 0
c 0
If I wanted to get everyone over 50, I'd get
neighborhood count
a 2
b 0
c 0
I tried
SELECT neighborhood, COUNT(*)
FROM persons
WHERE YEAR(NOW()) - persons.birthyear < 18
GROUP BY neighborhood;
but this gives me 0 rows, when instead I want 3 rows with distinct neighborhoods and 0 count for each. How would I accomplish this?
You can use conditional aggregation:
SELECT neighborhood, SUM(YEAR(NOW()) - p.birthyear) as under_18,
SUM(YEAR(NOW()) - p.birthyear BETWEEN 34 AND 42) as age_34_42
FROM persons p
GROUP BY neighborhood;
I think that if the count is 0, the row doesn't appear.
Your code seems correct to me, if you try it on the example with age 50, it should give you one row whith the expected line (neighborhood:a,count:2)
I would recommend using a sub query:
SELECT
count(*) [group-by-count-greater-than-ten]
FROM
(
SELECT
columnFoo,
count(*) cnt
FROM barTable
WHERE columnBaz = "barbaz"
GROUP BY columnFoo
)
AS subQuery
WHERE cnt > 10
In the above, the subquery return result set is being used by the main query as any other table.
The column cnt is no longer seen by the main query as a computed field and does not have to reference the count() function.
However, inside the subquery running a where clause or a having clause that must look at the alias cnt column, the count() function would have to be referenced as referencing cnt in the subquery would throw an error.
In your case using a subquery would look something like this.
SELECT
neighborhood,
age,
count(*) as cnt
FROM
(
SELECT
*,
(YEAR(NOW()) - birthyear) as age
FROM PERSONS
) as WithAge
WHERE age < 18
GROUP BY neighborhood, age
I want to write a sql query to get best product of each year from a table . I have grouped the product-id and sum the qty to get the total number of products per id.
I converted the datetime function into year to get the year but output is wrong..
Anyone can help me with this?
SELECT Year(ModifiedDate), ProductID, SUM(OrderQty) AS TotalQuantity
from Sales.SalesOrderDetail
GROUP BY ProductID, year(ModifiedDate)
having count(*) > 3000
ORDER BY SUM(OrderQty) DESC
From your comment:
query is working fine if the set having condition to 2000. but if i
set it to 3000 it return nothing. if i use this "having count() >
2000" so i get two records. first of 2013 which return total quantity
3913 and record of 2014 with total quantity 2902. but when i change
condition to this "having count() > 3000 " it return nothing. but it
should return the 2013 record
You select the sum of OrderQty, yet you filter on the count and expect it to be the same. Count is the number of records, it doesn't care about the actual values in the records.
When you filter with
having sum(OrderQty) > 3000
you will only get the 2013 record.
We can do it in two-part.
I) create a temporary table for year-wise, id wise sum of qty.
create table tempSaleOrderDetail as select year(ModifiedDate) year,sum(OrderQty) orderqty, ProductID from Sales.SalesOrderDetail group by year(ModifiedDate), productId order by 1 desc,2 desc;
II) Fetch the data.
select A.* from tempSaleOrderDetail A inner join (select year ,max(orderqty) orderqty from tempSaleOrderDetail group by year) B on A.year=B.year and A.orderqty=B.orderqty ;
If any year has more than one Id's performance is same so this query will give both results.
I have table like this
enter image description here
I need to get the data only whose age > 10, along with that i need to get the total number of records present in the table. ie. in this example it is 4 records. what i need is in single query i need to get the total number of records present in table and columns which i query.
Query will be somewhat like
SELECT ID, NAME, count(TOTAL NUMBER OF RECORDS IN TABLE) as Count from MYTABLE WHERE AGE > 10
Any idea about this ?
You can use a subquery in the FROM clause:
SELECT ID, NAME, c.cnt as Count
FROM MYTABLE CROSS JOIN
(SELECT COUNT(*) as cnt FROM MYTABLE) c
WHERE AGE > 10 ;
Both databases support window functions, but they are not really helpful here, because the count is not filtered in the same way as the outer query. If you do want the filter for both, then in the most recent versions you can do:
SELECT ID, NAME, COUNT(*) OVER () as cnt
FROM MYTABLE
WHERE AGE > 10 ;
You can try below - using scalar subquery
SELECT ID, NAME, age,(select count(*) from mytable WHERE AGE > 10) as Count
from MYTABLE
WHERE AGE > 10
I have a voting application that writes values to a mysql db table. It is a preference/weighted voting system so people choose a first option, second option, and third option. These all go into separate fields in the table. I'm looking for a way to write a query that will assign numerical values to the responses (3 for a first response, 2 for a second, 1 for a first) and then display the value with the summed score. I've been able to do this for total number of votes
select count(name) as votes,name
from (select 1st_option as name from votes
union all
select 2nd_option from votes
union all
select 3rd_option from votes) as tbl
group by name
having count(name) > 0
order by 1 desc;
but haven't quite figured out how to assign values to response in each column and then pull them together. Any help is much appreciated. Thanks!
You could do something like this:
select sum(score) as votes,name
from (select 1st_option as name, 3 as score from votes
union all
select 2nd_option as name, 2 as score from votes
union all
select 3rd_option as name, 1 as score from votes) as tbl
group by name;
I have a table like this:
Votes (id, person, positive_vote, negative_vote)
I want to group by person and and sort by total votes for each person. I know how to get the total sum of a single column for a group, but I can't figure out how to get the total of all the sum for each group (the total votes).
Here's what I have so far:
SELECT person, sum(positive_vote), sum(negative_vote) FROM Votes GROUP BY person;
Try,
SELECT person,
sum(positive_vote) totalPositive,
sum(negative_vote) totalNegative,
(sum(positive_vote) + sum(negative_vote)) totalVotes
FROM Votes
GROUP BY person
-- HAVING (sum(positive_vote) + sum(negative_vote)) < 5
If you want the total for each person, just subtract the sums (or add them instead if you just want a total number of votes):
SELECT person, sum(positive_vote), sum(negative_vote),
SUM(positive_vote)-SUM(negative_vote)
FROM Votes
GROUP BY person
Note I have subtracted the sums here and not summed the difference of the columns themselves because I do not know how you are storing data in your table and NULLs can do funny things with math.
SELECT Z.person,Z.sum_pv,Z.sum_nv,Z.diff_sum_pv_nv
FROM
(SELECT person, sum(positive_vote) AS sum_pv, sum(negative_vote) sum_nv,sum(positive_vote) - sum(negative_vote) AS diff_sum_pv_nv
FROM Votes GROUP BY person)Z;
Do you mean the sum of positive_vote and negative_vote?
SELECT
person,
SUM(positive_vote) AS positive_votes,
SUM(negative_vote) AS negative_votes,
SUM(positive_vote + negative_vote) AS total_votes
FROM Votes GROUP BY person;
SELECT person,
sum(positive_vote) as totalPositive,
sum(negative_vote) as totalNegative,
(sum(positive_vote + negative_vote)) as totalVotes
FROM Votes
GROUP BY person