Say you have a 3 level hierarchy as follows: Household (1-m) --> Person (1-m) --> Account
But there are only 2 Tables:
Person (3 columns are):
Person_id, person_name, household_key
and
Account (3 columns are):
Account_id, account_name, person_id
What are some ways to get a query that returns these results (ie ordered by household, person then account):
Household_key Person_id Account_id
1 1 456
1 2 763
1 2 801
1 2 822
2 3 54
2 4 68
Judging from the desired result that doesn't look like a hierarchy query to me - try
SELECT DISTINCT
P.Household_key,
P.Person_id,
A.Account_id
FROM
Person P
INNER JOIN Account A ON P.Person_id = A.Person_id
ORDER BY
P.Household_key,
P.Person_id,
A.Account_id
IF I am mistaken THEN you will need to show some sample data in the tables Person and Account .
Related
I'm trying to write a query that returns pairs of users that have the same number of loans.
I have this table:
LOANS
id_loan book_barcode id_user
1 123 1
2 321 2
3 456 3
4 678 4
5 721 1
6 934 2
That's my code how to get pairs of users:
SELECT l1.id_user user_1, l2.id_user user_2
FROM loans l1
JOIN loans l2 ON l2.id_user > l2.id_user
GROUP BY l2.id_user, l2.id_user;
This is what I want from my query, but I don't know how to compare in the right way two counts, I tried but it didn't work.
id_user1 id_user2 number_loan
1 2 2
3 4 1
The most reasonable way is to aggregate the loans before joining:
with u as (
select id_user, count(*) as num_loans
from loans l
group by id_user
)
select u1.id_user, u2.id_user
from u u1 join
u u2
on u1.num_loans = u2.num_loans and u1.id_user < u2.id_user;
You could do this without pre-aggregating, but the query will be much more expensive:
select u1.id_user, u2.id_user
from loans u1 join
loans u2
on u1.id_user < u2.id_user
group by u1.id_user, u2.id_user
having count(distinct u1.id_loan) = count(distinct u2.id_loan);
I don't recommend this approach.
SQL Server 2012.
Each enterprise has one or more teams. Each team can have sponsors or cannot have any sponsors.
Enterprise
Id Name
1 A
2 B
3 C
and the team table:
Team
Id Name EnterpiseId
1 For 1
2 Xor 2
3 Nor 2
4 Xur 1
5 Fir 3
6 Fte 2
and now the table sponsor
Sponsor
id Name TeamId
1 XX1 1
2 FC7 1
3 89U 3
Now I need to know how to present this table that shows only the enterprises that have at least one sponsor.
FINAL TABLE
Id Name
1 A
3 C
The enterprise B has 3 teams, but there are no sponsors for those 3 teams, so I want to show the enterprises that have sponsors which are "A" and "C".
Select A.id, A.name
FROM Enterprise A
LEFT JOIN Team B on A.Id=b.EnterpriseId
INNER JOIN Sponsor C on B.Id=C.TeamId
Where (SELECT COUNT(*) FROM Sponsor S INNER JOIN Team T on T.id=S.TeamId group by T.id)>0
This is not working. I am not used to use subsets which is likely the way to achieve the desired table. Thanks.
You can do this with JOINs. The GROUP BY is just to eliminate duplicates:
SELECT e.id, e.name
FROM Enterprise e JOIN
Team t
ON e.Id = t.EnterpriseId JOIN
Sponsor s
ON t.Id = s.TeamId
GROUP BY e.id, e.name;
The JOIN only matches teams that have sponsors.
If you were looking for more than one, then something like HAVING COUNT(*) > 1 would be called for.
I am trying to write a query using group by in sub query ,I referred lot of blogs but could not get all the values.
I have three tables and below is the structure of those tables.
Pet_Seller_Master
ps_id ps_name city_id
2 abc 1
3 xyz 2
4 fer 4
5 bbb 1
City_Master
city_id city_name
1 Bangalore
2 COIMBATORE
4 MYSORE
Api_Entry
api_id ps_id otp
1 2 yes
2 3
3 2 yes
4 3 yes
5 4
6 5 yes
7 5 yes
8 5 yes
Query is to get number of sellers, no of pet sellers with zero otp, no of pet sellers with 1 otp, no of pet sellers with 2 otp,no of pet sellers with otp>2 for the particular city and within date range.
Through Below query I am able to get city , psp , and zero otp
select cm.city_name,
count(ps.ps_id) as PSP,
((select count(ps1.ps_id)
FROM ps_master ps1
WHERE ps1.city = cm.city_id)-
(SELECT count(distinct ps1.ps_id)
from ps_master ps1
INNER JOIN api_entry ae ON ps1.ps_id = ae.ps_id and otp!=''
WHERE ps1.city = cm.city_id and date(timestamp) >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY AND date(timestamp) < curdate())) as zero_psp
from ps_master ps INNER JOIN city_master cm ON ps.city = cm.city_id and cm.city_type = 'IN HOUSE PNS'
group by city_id
Please tell me the solution to solve this query.
Thanks in advance
It's not hard to do and you were on a right track. Here is what I would use:
select c.city_name, a.otp, p.ps_name, COUNT(*) nbr
from Api_Entry a
inner join Pet_Seller_Master p on p.ps_id=a.ps_id
inner join City_Master c on p.city_id=c.city_id
group by c.city_name, a.otp, p.ps_name
Now, if you want to get the number of sellers with zero otp, you just apply where clause:
where otp <> 'yes'
If you want to get the number of pet sellers with otp>2, then you just use subquery:
select *
from (
select c.city_name, a.otp, p.ps_name, COUNT(*) nbr
from #tempA a
inner join #tempP p on p.ps_id=a.ps_id
inner join #tempC c on p.city_id=c.city_id
group by c.city_name, a.otp, p.ps_name
) g
where nbr > 2
Let's say I have two tables. A students table and an observations table. If the students table looks like:
Id Student Grade
1 Alex 3
2 Barney 3
3 Cara 4
4 Diana 4
And the observations table looks like:
Id Student_Id Observation_Type
1 1 A
2 1 B
3 3 A
4 2 A
5 4 B
6 3 A
7 2 B
8 4 B
9 1 A
Basically, the result I'd like from the query would be the following:
Student Grade Observation_A_Count
Alex 3 2
Barney 3 1
Cara 4 2
Diana 4 0
In other words, I'd like to gather data for each student from the students table and for each student count the number of A observations from the observations table and tack that onto the other information. How do I go about doing this?
This is a simple join and aggregate:
select
a.Student,
a.Grade,
count(b.Id) as Observation_A_Count
from
Student a left join
Observations b on a.Id = b.Student_Id
group by
a.Student,
a.Grade
order by
1
Or, you can use a correlated subquery:
select
a.Student,
a.Grade,
(select count(*) from observations x where x.Student_Id = a.Id) as Observation_A_Count
from
Student a
order by
a.Student
You can join the table with a specific condition, by doing this you can have a field for Observation_B_Count and Observation_C_Count, etc.
SELECT Student.Student, Student.Grade, COUNT(Observation_Type.*) AS Observation_A_Count
FROM Student
LEFT JOIN Observations ON Observations.Student_ID = Student.Student_ID AND Observations.Observation_Type = 'A'
GROUP BY Student.Student, Student.Grade
I have a Master and Detail table, the Detail linking to the Master record on a FK reference.
I need to display all the data from the Master table, and the corresponding number of details for each record, i.e.
MASTER TABLE
ID Name Age
1 John 15
2 Jane 14
3 Joe 15
DETAIL
MasterID Subjects
1 Trigonometry
1 Chemistry
1 Physics
1 History
2 Trigonometry
2 Physics
Thus, when I ran the SQL statement, I would have the following result:
ID Name Age #Subjects
1 John 15 4
2 Jane 14 2
3 Joe 15 0
Thanks!
This may be useful
SELECT mt.ID, mt.NAME, mt.AGE, COUNT(d.MasterID) as [#Subjects]
FROM MasterTable mt
LEFT OUTER JOIN Detail d on mt.ID = d.ID
GROUP BY mt.ID, mt.NAME, mt.AGE
ORDER BY mt.ID
select id,
name,
age,
( select count(*)
from detail
where master.id = detail.id ) as record_count
from master
syntax adjusted depending on what db you are using