SQL Group By Help Required - sql

I have a table named People in the following format:
Date | Name.
When I count the people by Grouping By Name with
Select Date, Name, count(*)
From People
Group By Date, Name;
Will give the following
Date Name count(*)
10 Peter 25
10 John 30
10 Mark 25
11 Peter 15
11 John 10
11 Mark 5
But I would like the following result:
Date Peter John Mark
10 25 30 25
11 15 10 5
Is this possible? This is a simple example of a more complicated database. If someone helps me in solving this problem I will use the concept to implement it in my table
Thanks!

Select Date
, count(case when Name = 'Peter' then 1 else null end)
, count(case when Name = 'John' then 1 else null end)
, count(case when Name = 'Mark' then 1 else null end)
From People
Group By Date;

another option different from turbanoff's if, for some reason, you find yourself in a situation that you cant apply a group by:
Select distinct(P.Date),
(select count(*) from People where date=p.date and name='Peter') as Peter,
(select count(*) from People where date=p.date and name='John') as John,
(select count(*) from People where date=p.date and name='Mark') as Mark
From People P

Related

distinct on with case when

I need your help with conditional "distinct on".
For example I have a table "users".
id
name
age
1
John
17
2
Sam
18
3
John
12
4
Sam
19
And I want to do something like:
select case when (u.age > 17) then (distinct on u.name u.*) else (u.*) from users u order by u.name
And I want to do "distinct on" BUT with exclusion, if age is less than 17, then display them as well, if age is greater then take random one.
The output I want is:
id
name
age
1
John
17
2
Sam
18
3
John
12
There are two users with name Sam, and both have age > 17, then I want to apply distinct on in this case.
But there's at least 1 John with age less than 17, therefore I want to have all users with name John in the output.
It might be possible to put this in a condition, but in my opinion, that leads to bad readability.
I would prefer to use UNION ALL here to clearly split these two parts of your query:
SELECT DISTINCT ON (name) id, name, age
FROM users
WHERE age > 17
UNION ALL
SELECT id, name, age
FROM users
WHERE age <= 17
ORDER BY id;
And yes, I know this will select twice from the table, but I think this better in this case unless you observe a very poor performance using this query.

Separate distinct values in to columns

Hi all I am quite new to SQL. I have a table (TABLE1) with two columns as below
Name age
--------
jim 18
jim 21
dave 18
dave 18
john 23
john 41
I need to create a view in SSMS which lists distinct ages for each name in a separate column as below
Jim Dave John
---------------
18 18 23
21 41
I have tried a sub query like
SELECT DISTINCT AGE FROM TABLE1 WHERE NAME = JIM
But I encountered a sub query cannot return more than one value.
You can use row_number() & do aggregation :
select max(case when name = 'jim' then age end) as jim,
max(case when name = 'dave' then age end) as dave,
max(case when name = 'john' then age end) as john
from (select t.*, row_number() over (partition by name order by age) as seq
from table t
) t
group by seq;

How to find rows where the same column has only the same another column

Suppose following table:
Name Age Occupation
Alex 20 Student
Alex 20 Seller
Alex 20 Minister
Liza 19 Student
Liza 20 Volunteer
Liza 21 HR partner
I want to find names which have only (and only) 20 in age column. So from this table I want to get all "Alex" rows and no "Liza" rows at all.
Thanks!
You need to use Group By and Having clause. Try this way
select Name
from table
group by Name
having count(case when Age = 20 then 1 end) = count(*)
count(case when Age = 20 then 1 end) counts only when age = 20 if it is equal to total count then the name has only 20 as age.
Just one another way:
select Name
from table
group by Name
having min(Age) = 20 and max(Age) = 20
One way is using NOT IN():
SELECT Name, Age, Occupation
FROM YourTable
WHERE Age = 20
AND Name NOT IN (SELECT Name FROM YourTable WHERE Age <> 20)

SQL Select for each Age Group and COUNT Members

I have the following tables
[Members]:
MemberID DOB Name
------------------------------------
1 01/01/2000 Jon
2 01/01/2005 Bob
3 01/01/2009 Mike
4 01/01/1980 Greg
[AgeGroups]:
GroupID GroupTitle MinAge MaxAge
--------------------------------------------------
1 GroupA 0 5
2 GroupB 6 10
3 GroupC 11 18
[Events]:
EventID EventStart
---------------------------
1 01/01/2015
I want to be able to do a SQL select command which gets the Group Title and a count of the number of members who's age will be within the age range of each of the Age Groups at the date of the EventStart.
GroupTitle MemberCount
----------------------------------
GroupA 1
GroupB 2
GroupC 1
I've been trying to do this with SELECT CASE WHEN but have got stuck.
Any help would be greatly appreciated!
Take a look at Date and Time Data Types and Functions, and in particular at the DATEDIFF function.
You could try something like the following:
SELECT AgeGroups.GroupID, AgeGroups.GroupTitle, COUNT(1) AS MemberCount
FROM AgeGroups
JOIN Events ON EventID = 1
JOIN Members
ON DATEDIFF(year, Members.DOB, Events.EventStart) >= AgeGroups.MinAge
AND DATEDIFF(year, Members.DOB, Events.EventStart) <= AgeGroups.MaxAge
ORDER BY AgeGroups.GroupID
Does that help?

Sum(case results not right

I have a contact table that includes the length of time each contact lived in the neighborhood:
ID First_Name Last_Name Neighborhood_Time
1 John Smith 1-2 years
2 Mary Jones 2-5 years
3 Dennis White 2-5 years
4 Martha Olson 5+ years
5 Jeff Black 5+ years
6 Jean Rogers 2-5 years
I want to show the percentage of time, the result would look like this:
One_to_2_Years Two_to_5_Years 5+_Years
16 50 33
This is what I'm using:
select
sum(case when Neighborhoods_time ='1-2 years' then 1 else 0 end)*100/(select count(*) from contact) as One_to_2_Years,
sum(case when Neighborhoods_time ='2-5 years' then 1 else 0 end)*100/(select count(*) from contact) as Two_to_6_Years,
sum(case when Neighborhoods_time ='5+years' then 1 else 0 end)*100/(select count(*) from contact) as Six_to_10_Years
from dbo.contact
This is my result:
One_to_2_Years Two_to_5_Years 5+_Years
0 0 16
16 33 0
0 16 16
I see the numbers under each column are correct, I'm having a problem summing them.
What am I missing?
Thanks.
Add Group by Neighborhoods_time
The basis of your query can be produced like
select
Neighborhood_Time,
100*COUNT(*)/(Select COUNT(*) from contact) as percentvalue
from
contact
group by
Neighborhood_Time
If you want to arrange it horizontally, then you should use a pivot
select
*
from
(
select
Neighborhood_Time,
100*COUNT(*)/(Select COUNT(*) from contact) as percentvalue
from
contact
group by
Neighborhood_Time
) src
PIVOT
( SUM(percentvalue) for Neighborhood_Time in ([1-2 years],[2-5 years],[5+ years])) as pt