Gather the number of customer by street - sql

I have two tables :
Customer:
id
name
address_id
1
John
4
2
Kate
5
3
Bob
2
4
Michael
2
5
Adriana
3
6
Ann
1
Address:
id
detail_str_name
city
district
street_name
1
France,Paris,str.2,N5
Paris
Paris
str.2
2
France,Parise,str.2 ,N3
Paris
Paris
str.2
3
France, Lille ,str.3,N4
Lille
Lille
str.3
4
France,Paris,str.4,N3
Paris
Paris
str.4
5
France, Paris, Batignolles,N4
Paris
Batignolles
Batignolles
I want table like this:
name
detail_str_name
city
district
street_name
sum(cu.num_cust)
John
France,Paris,str.4,N3
Paris
Paris
str.4
1
Kate
France, Paris, Batignolles,N4
Paris
Batignolles
Batignolles
1
Bob
France,Parise,str.2 ,N3
Paris
Paris
str.2
3
Michael
France,Parise,str.2 ,N3
Paris
Paris
str.2
3
Adriana
France, Lille ,str.3,N4
Lille
Lille
str.3
1
Ann
France,Paris,str.2,N5
Paris
Paris
str.2
3
I want to count customer group by city,district and street_name, not detail_str_name.
I try:
select cu..name,ad.detail_str_name, ad.city,ad.district, ad.street_name,sum(cu.num_cust)
from
(select address_id, name,count (id) as num_cust
from customer
group by address_id,name) cu
left join address ad on cu.address_id = ad.id
group by cu..name,ad.detail_str_name, ad.city,ad.district, ad.street_name
But,this code groups by detail_str_name,
Which does not suit me.
What can I change?

I haven't been able to check this so it might not be totally correct but I think the query below should get the data you require.
This SQLTutorial article on the partition by clause might be useful.
SELECT cu.name,
ad.detail_str_name,
ad.city,
ad.district,
ad.street_name,
COUNT(cu.name) OVER(PARTITION BY ad.city, ad.district, ad.street_name) AS 'num_cust'
FROM customer cu
JOIN address ad ON ad.id = cu.address_id

Related

Use inner join and left join with more than 2 tables? [duplicate]

This question already exists:
Use left join and inner join with more than 2 tables
Closed 4 months ago.
Here you can see I have three tables
Student table
Stud_id Name Br_id Email City_id
1001 Ankit 101 ankit#bmail.com 1
1002 Pranav 105 pranav#bmail.com 2
1003 Raj 102 raj#bmail.com 2
1004 Shyam 112 shyam#bmail.com 4
1005 Duke 112 duke#bmail.com 2
1006 Jhon 102 jhon#bmail.com 3
1007 Aman 101 aman#bmail.com 4
1008 Pavan 111 pavan#bmail.com 13
1009 Virat 112 virat#bmail.com 12
Branch Table
Br_id Br_name HOD Contact
101 CSE SH Rao 22345
102 MECH AP Sharma 28210
103 EXTC VK Reddy 34152
104 CHEM SK Mehta 45612
105 IT VL Shelke 22521
106 AI KH Verma 12332
107 PROD PG Kakde 90876
Address Table
City_id City Pincode
1 Mumbai 400121
2 Pune 450011
3 Lucknow 553001
4 Delhi 443221
5 Kolkata 213445
6 Chennai 345432
7 Nagpur 323451
8 Sri Nagar 321321
I am using here three tables first one is a student table and the second one is a Branch table and the third one is an Address table
So I am writing a query like this here you can see below
select [Name], Br_name, City
from student
inner join Branch on student.Br_id = Branch.Br_id
left join [Address] on student.City_id = [Address].City_id
I have three tables I want to show here the student's name and branch name city name, but I want to show the student who has their branch only. I also want to show the student who has their city as well as show a student who does not have any city.
I wrote the query above but here I am not getting the result. Here student's name who does not have any city what's wrong here in my above join SQL query?
Here as you can see I am getting this result which I do not want to show
Name Br_name City
Ankit CSE Mumbai
Pranav IT Pune
Raj MECH Pune
Jhon MECH Lucknow
Aman CSE Delhi
Why can I not get the students who do not have a city and who have a city? What's wrong here in my join query what I am missing here?
Please let me know what's wrong in my above join query what should I do to get proper result? I have given three tables above
You can see that and why I am not able to get the result what I want to show what is the wrong in the above my join query please let me know
I hope someone will help me. Thank you so much.

Sql distinct group of rows

In sql i want get distict sets of rows : identical group for Characteristic and Value only one time :
The column Characteristic can range from one to 10
Table :
Name
Characteristic
Value
Mary
eyes
Blu
Mary
hair
blonde
Mary
Sex
Female
Jhon
eyes
Black
Jhon
Hair
Black
Jhon
Sex
Male
Jhon
Nation
Franch
Bill
eyes
Blu
Bill
Hair
Blond
Bill
Sex
Male
Will
eyes
Green
Will
Hair
Blond
Will
Sex
Male
Will
Nation
Spain
Lilly
eyes
Blu
Lilly
Hair
Blonde
Lilly
Sex
Female
mark
eyes
Black
mark
Hair
Black
mark
Sex
Male
mark
Nation
Franch
Anna
eyes
Blu
Anna
Hair
Blonde
Anna
Sex
Female
Antonio
eyes
Black
Antonio
Hair
Black
Antonio
Sex
Male
Antonio
Nation
Franch
The result that i want to achieve :
Group
Characteristic
Value
1
eyes
Blu
1
Hair
Blonde
1
Sex
Female
2
eyes
Black
2
Hair
Black
2
Sex
Male
2
Nation
Franch
3
eyes
Blu
3
Hair
Blond
3
Sex
Male
4
eyes
Green
4
Hair
Blode
4
Sex
Male
4
Nation
Spain
and finally if it's possible :
Name
Characteristic
Value
Group
Mary
eyes
Blu
1
Mary
Hair
Blonde
1
Mary
Sex
Female
1
Jhon
eyes
Black
2
Jhon
Hair
Black
2
Jhon
Sex
Male
2
Jhon
Nation
Franch
2
Bill
eyes
Blu
3
Bill
Hair
Blond
3
Bill
Sex
Male
3
Will
eyes
Green
4
Will
Hair
Blond
4
Will
Sex
Male
4
Will
Nation
Spain
4
Lilly
eyes
Blu
1
Lilly
Hair
Blonde
1
Lilly
Sex
Female
1
mark
eyes
Black
2
mark
Hair
Black
2
mark
Sex
Male
2
mark
Nation
Franch
2
Anna
eyes
Blu
1
Anna
Hair
Blonde
1
Anna
Sex
Female
1
Antonio
eyes
Black
2
Antonio
Hair
Black
2
Antonio
Sex
Male
2
Antonio
Nation
Franch
2
You can use STRING_AGG to join all the characteristics together, then use ROW_NUMBER and DENSE_RANK to count them. Then you re-join that back to the base table.
For your first query, you can do it like this.
SELECT
Groups.GroupId,
t.Characteristic,
t.Value
FROM YourTable t
JOIN (
SELECT
t.Name,
t.GroupDefinition,
GroupId = DENSE_RANK() OVER (ORDER BY t.GroupDefinition),
RowId = ROW_NUMBER() OVER (PARTITION BY t.GroupDefinition ORDER BY t.Name)
FROM (
SELECT
t.Name,
GroupDefinition = STRING_AGG(Characteristic + ':' + Value, '|')
WITHIN GROUP (ORDER BY t.Characteristic)
FROM YourTable t
GROUP BY
t.Name
) t
) Groups ON Groups.Name = t.Name
WHERE Groups.RowId = 1;
The second query is as follows.
SELECT
Groups.GroupId,
t.*
FROM YourTable t
JOIN (
SELECT
t.Name,
t.GroupDefinition,
GroupId = DENSE_RANK() OVER (ORDER BY t.GroupDefinition),
RowId = ROW_NUMBER() OVER (PARTITION BY t.GroupDefinition ORDER BY t.Name)
FROM (
SELECT
t.Name,
GroupDefinition = STRING_AGG(Characteristic + ':' + Value, '|')
WITHIN GROUP (ORDER BY t.Characteristic)
FROM YourTable t
GROUP BY
t.Name
) t
) Groups ON Groups.Name = t.Name;
db<>fiddle
Another option would be to aggregate it into a JSON or XML format, then shred it back out without re-joining the base table.

How to get the list of people who do NOT have citizenship of country X in SQL

I have the 3 following tables
People
Id
Name
Age
1
Bob
23
2
John
25
3
Fred
37
4
Avery
42
Citizenship
Person_ID
Country_ID
1
2
1
1
2
1
2
5
3
2
3
6
4
3
4
4
Country
Country_ID
Country_Name
Capital_City
1
UK
London
2
France
Paris
3
Canada
Ottawa
4
Australia
Canberra
5
Germany
Berlin
6
Russia
Moscow
The goal here is to find all people who do NOT have French citizenship. My initial query was as follows
SELECT p.name
FROM People p
LEFT JOIN Citizenship ct
ON p.id = ct.person_id
LEFT JOIN Country c
ON ct.country_id = c.country_id
WHERE c.country_name != 'France';
However, the result doesn't seem to be correct. What condition am I missing in this query?

Why does my view query split into two?

I am trying to create a view that records the selected attributes for all Computer Science majors.
This is my query to create a view:
DROP VIEW CS_grade_report;
CREATE VIEW CS_grade_report AS
SELECT Student.student_id AS "ID",
student_name AS "Name",
course_number AS "Course #",
credit AS "Credit",
grade AS Grade
FROM Student, Class, Enrolls
WHERE major = 'CSCI'
AND Student.student_id = Enrolls.student_id
AND Class.schedule_num = Enrolls.schedule_num;
SELECT *
FROM CS_grade_report;
And this is what is generated:
ID Name Course # Credit GR
------ ------------------------- -------- ---------- --
600000 John Smith CSCI3200 4 B+
600000 John Smith CSCI3700 3 C
600000 John Smith SPAN1004 3 A-
600000 John Smith CSCI4300 3 A+
600001 Andrew Tram MUSC2406 2 A+
600001 Andrew Tram SPAN1004 3 A
600001 Andrew Tram CSCI3700 3 B-
600002 Jane Doe CSCI4200 3 D+
600003 Michael Jordan CSCI4300 3 A+
600004 Tiger Woods MUSC1000 1 A
600007 Dominique Davis CSCI4300 3 F
ID Name Course # Credit GR
------ ------------------------- -------- ---------- --
600009 Will Smith CSCI3200 4 A
600010 Papa Johns CSCI3200 4 B
600011 John Doe CSCI3200 4 C
600012 Jackie Chan CSCI3200 4 D
600013 Some Guy CSCI3200 4 E
16 rows selected.
I am assuming this is output from sqlplus. There is a "pagesize" option to define when breaks are added. If you only want to see one heading, set the size to a large enough value prior to running your SELECT statement as such:
set pagesize 500
(or whatever size you want)
There are many command options for sqlplus. This link is a good cheat-sheet.

Returning only records that have matching fields in other records

I have a query that returns a list of customers and their addresses.
ID FName LName Address1 City Postcode
--------------------------------------------------------
1 James Smith 1 Bank Street London W1C 1AA
2 Sarah Jones 45 Moor Ave London SW1 1YH
3 Mary Smith 1 Bank Street London W1C 1AA
4 Sean Baker 17 White Blvd London SE3 7TH
5 Bob Patel 58B Canal St London NW2 2TT
6 Seeta Patel 58B Canal St London NW2 2TT
7 David Hound 4 Main St London E11 8AB
I'm trying to produce another query from this data that selects a list of customers who are related/living together.The criteria for this would be the same Address 1 and Postcode fields.
My question is how I can produce a query that only selects records that have at least 1 other record with matching [Address1] and [Postcode]? ie; in the above example return only records 1, 3, 5 and 6.
Select * From
Customers c JOIN
(SELECT Address1, PostCode FROM Customer GROUP BY Address1, PostCode HAVING Count(1) > 1) c2
ON c.Address1 = c2.Address1 AND c.PostCode = c2.PostCode