SQL joining to the same column id - sql

I have a simple SQL query I just get to work out right. I've put together a test database like this;
TABLE MAIN
id name groupone grouptwo
1 Fred 1 3
2 bob 2 1
TABLE DETAIL
id group groupname
1 1 onegrp
2 2 twogrp
4 3 threegrp
My Select query is;
SELECT name, groupone, grouptwo, groupname
FROM main
INNER JOIN detail
ON main.groupone = detail.group
WHERE main.id = 1
The result I get is;
id name groupone grouptwo groupname
1 fred 1 3 onegrp
How do I change this to instead of giving the result as 1 and 3.
I get ... fred onegrp, threegrp
I've tried a dozen things but can't get it to work, I sort of want a give me the groupname again option but not sure what the syntax is for that! :(
Thanks in advance for your time and help

I think this is what you are after. You need to join the detail table twice, on the two different keys.
SELECT
m.Name
,a.groupname as 'GroupOne'
,b.groupname as 'GroupTwo'
FROM
main m
INNER JOIN
detail a
on m.groupone = a.group
INNER JOIN
detail b
on m.grouptwo = b.group
WHERE
m.id = 1

Related

SQL Selecting & Counting In the same query

thanks in advance for any help on this, I am a bit of a newbie to MS SQL and I want to do something that I think is achievable but don't have the know how.
I have a simple table called "suppliers" where I can do (SELECT id, name FROM suppliers ORDER BY id ASC)
id
name
1
ACME
2
First Stop Business Supplies
3
All in One Supply Warehouse
4
Farm First Supplies
I have another table called "products"
id
name
supplier_id
1
Item 1
2
2
Item 2
1
3
Item 3
1
4
Item 4
3
5
Item 5
2
I want to list all the suppliers and get the total amount of products for each supplier if that makes sense on the same row? I am just not sure how to pass the suppliers.id through the query to get the count.
I am hoping to get to this:
id
name
total_products
1
ACME
2
2
First Stop Business Supplies
2
3
All in One Supply Warehouse
1
4
Farm First Supplies
0
I really appreciate any help on this.
Three concepts to grasp here. Left Join, group by, and Count().
select s.id, s.name, Count(*) as total_products
from suppliers s
left join products p on s.id=p.supplier_id --the left join gets your no matches
group by s.id, s.name
left join is a join where all of the values from the first table are kept even if there are no matches in the second.
Group by is an aggregation tool where the columns to be aggregated are entered.
Count() is simply a count of transactions for the grouped columns.
Try this :-
SELECT id, name, C.total_products
FROM Suppliers S
OUTER APPLY (
SELECT Count(id) AS total_products
FROM Products P
WHERE P.supplier_id = S.id
) C

SQL: Unable to find a join or union to produce the following table

A Pupil table with { ID, LastName}
a Subject Table with {ID, SubjectName}
and a Report Table with {ID, PupilID, SubjectID, Grade}
There is a one-to-many relationship between Pupil and Report Tables, and Subject and Report Tables.
I want to generate a table like this for say subjectID = 1
Pupil.ID Pupil.LastName SubjectID Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
The problem is that the Report table would contain just 2 entries for subject 1:
PupilID SubjectID Grade
----1------- 1 ----------- B
----4------- 1 ----------- A
Left joins don't seem to work since there are only 2 entries in the report table for subject 1
SAMPLE DATA
{Pupil Table}
ID LastName
1 ...Smith
2 ...Jones
3 ...Weston
4 ...Knightly
{Subject Table}
ID SubjectName
1 ....Maths
2 ....Physics
3 ....Chemistry
{Report Table}
ID PupilID SubjectID Grade
1 .......1 ..........1 ..........B
2 .......4 ..........1 ..........A
When I do a search on SubjectID = 1 I want the table:
Pupil.ID .......Pupil.LastName ........SubjectID ...........Grade
1 --------------Smith ---------- 1 ------------B
2 --------------Jones ---------- 1 ------------NULL
3 -------------Weston ----------1 ------------NULL
4 -------------Knightly ---------1 -----------A
Access doesn't do subqueries very easily, so everything gets crammed into the FROM clause with a series of wrapped parentheses. Based on your sample data and my fighting Access to stop being unnecessarily difficult, I came up with this:
SELECT ps.Pupil_ID, ps.LastName, ps.Subject_ID, r.Grade
FROM (SELECT * FROM (SELECT ID AS Pupil_ID, LastName FROM Pupil) p,
(SELECT DISTINCT ID AS Subject_ID FROM Subject)) ps
LEFT JOIN REPORT r ON r.PupilID = ps.Pupil_ID AND r.SubjectID = ps.Subject_ID
ORDER BY Pupil_ID, Subject_ID;
The subquery "ps" is a cartesian join of the Pupil and Subject table views that I specified. At this point, your query would look like this:
(LastName column not shown for clarity)
StudentID|SubjectID
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
Now, using that Cartesian join subquery (pupilstudent -> ps), I use a LEFT JOIN to assign the Report table to each unique student's ID and subject ID. Therefore, if a student did not take a particular class, there will be a NULL value in the final result.
I tested this in Access using your sample data and it works on my machine.
Also as a note, it is poor practice to have a field called just ID in each table (e.g. in the Pupil table, ID becomes PupilID). This makes it much easier to use, and it self documents.
Cross join pupil and subject tables and left join result to report table
What you need is a cross join:
SELECT Pupil.ID, Pupil.LastName, SubjectID, Grade FROM
Pupil, Subject LEFT JOIN Report ON Subject.ID=Report.SubjectID
WHERE Subject.ID=1
To combine every pupil with every (or with a particular) subject, use cross join; Then use left join to get the corresponding grades:
select *
from pupil p cross join (select * from subject where id = 1) s
left join report on subjectId = s.id and pupilId = p.id

Get data from relational tables

I have following tables in my db.
Calls:
ID Name
1 Call1
2 Call2
3 Call3
Notes:
ID Name
1 Note 1
2 Note 2
Person:
ID Name
1 Andrew
PersonCalls:
ID CallID PersonID
1 1 1
2 2 1
PersonNotes:
ID NoteID PersonID
1 1 1
1 2 1
Now I need to get data from these tables according to person id. I am able to get data from 2 tables, for example Notes and PersonNotes, but I am not able to get combined data from these tables. This should be the result.
Result:
PersonID Note Call
1 Note1 Call1
1 Note2 Call2
Please suggest
Thanks
Use Join (ie: Inner Join):
select distinct p.ID as PersonID, n.Name as Note, c.Name as Call from Person p
inner join PersonCalls pc on p.ID = pc.PersonID
inner join PersonNotes pn on p.ID = pn.PersonID
inner join Calls c on pc.CallID = c.ID
inner join Notes n on pn.NoteID = n.ID
Without getting too detailed you can use a left join on dbo.calls.ID, dbo.notes.id, dbo.person.id, etc if you are using MS SQL server. Otherwise are you sure you can't just write a report?

multiple conditions in same column with relation

Here is the case:
There is a user table
id email orders_counter
=================================
1 a#a.com 5
2 b#b.com 3
3 c#c.com 0
And a user data table for user's other data
id user_id title value
=======================================
1 1 Name Peter Johnson
2 1 Tel 31546988
3 2 Name Alan Johnson
4 2 Tel 56984887
If I want to fetch all user that
1, orders_counter greater then 3
2, Name contain 'Johnson'
3, Tel contain '88'
AT THE SAME TIME
What is my sql, and if I want to do it rubyonrails way
what is the ActiveRecord code
I know I can it one by one and then join all of them together, but it waste too much resource while conditions build up
Select * From `user` u
inner join `userdata` d on d.user_id=u.id and d.title='Name' and d.value like '%Johnson%'
inner join `userdata` c on c.user_id=u.id and c.title='Tel' and c.value like '%88%'
where orders_counter > 3
the way that you've got your user data table structured, you'll almost always have to join on that table several times in order to "pivot" those values into columns. I'd recommend just creating a table that has name and tel as columns. then the query becomes a lot more simple
select * from `user` u
inner join `user_data` d on d.Tel like '%88%' and d.Name like '%johnson%'
where u.orders_counter > 3
try this one up,
SELECT a.*, b.*
FROM user a
INNER JOIN data b
ON a.id = b.user_ID
WHERE a.orders_counter > 3 AND
(b.title = 'NAME' AND b.value like '%johnson%') AND
(b.title = 'TEL' AND b.tel like '%88%')
try this:
select *
from user U join user_data D
on U.id=D.user_id
where U.orders_counter>3
and D.title='Name' and value like '%Johnson%'
and D.title='Tel' and value like '%88%'

SQl Left Join Query

These are the tables that i have(I got this):
table building: b_id(key relation with table build-works b_id):1 2 3
field1: buildingA, buildingB,
buildingC
table build-works: b_id:1 1 2 3 3 3
w_id: 1 2 1 1 2 3
table works: w_id(key relation with table build-works w_id): 1 2 3 4
field1: electricity, sanitary, shell,
roofing
Now I want to know the works per building?
How can i do this with sql, and can you give my the example also with zend_db?
Thanks
using left joins since its in the title
SELECT *
FROM building b
LEFT JOIN buildworks bw
ON b.b_id = bw.b_od
LEFT JOIN works w
ON bw.w_id = w.w_id
Assuming b_id is the primary key for building, (b_id, w_id) is key for build_works, and w_id is key for works you can do it as follows:
Project_building.field1,works.field1(building JOIN build_works JOIN works)
Note that you have to rename field1 of works to something else when doing JOIN.
Also note that this might not be the most efficient way to do it.