How To Join These Tables in SQL normalising - sql

I want to Join two tables in sql
e.g.:
Table 1
ID
1
2
3
Table 2
ID SEC
1 Hospital
1 Medical
2 Clinic
2 University
3 College
I want result like
ID SEC
1 Hospital, Medical
2 CLinic, University
3 College

You can use the group_concat aggregate function, which would actually allow you to do this without even joining:
EDIT: Now that the comment explained the question is actually about sqlite and not mysql as it was initially tagged, the syntax is slightly different:
SELECT id, GROUP_CONCAT(SEC, ', ')
FROM table2
GROUP BY id

JOIN and then use GROUP_CONCAT with group by.
select T1.id , GROUP_CONCAT(SEC SEPERATOR ',')
FROM Table1 T1
JOIN Table2 T2
on T1.id = T2.id
GROUP BY T1.id

Related

SQL: Joining two tables and selecting top N in group from one table

I am using MsAccess and will upsize to sql soon.
I have this scenario:
Table 1 : UserID Name
Table 2 : GradeID Date Grade UserID
What I want to do is join both tables in a query or report to list all users alphabetically and their latest 2 grades. I looked up 'top n in group' solutions but can't figure them out or many didn't work. Currently I use Inner Join but that list all grades
Solution should look like:
User1 John Grade30 date grade
user1 John Grade29 date grade
user2 bob Grade41 date grade
user2 bob Grade13 date grade
thank you!
This is tricky in MS Access. One method uses a correlated subquery:
select t1.*, t2.grade, t2.date
from table1 as t1 inner join
table2 as t2
on t1.userId = t2.userId
where t2.date in (select top (2) tt2.date
from table2 as tt2
where tt2.userId = t2.userId
order by tt2.date
);

SQL Subquery Join and Sum

I have Table 1 & 2 with common Column name ID in both.
Table 1 has duplicate entries of rows which I was able to trim using:
SELECT DISTINCT
Table 2 has duplicate numeric entries(dollarspent) for ID's which I needed and was able to sum up:
Table 1 Table 2
------------ ------------------
ID spec ID Dol1 Dol2
54 A 54 1 0
54 A 54 2 1
55 B 55 0 2
56 C 55 3 0
-I need to join these two queries into one so I get a resultant JOIN of Table 1 & Table 2 ON column ID, (a) without duplicates in Table 1 & (b) Summed $ values from Table 2
For eg:
NewTable
----------------------------------------
ID Spec Dol1 Dol2
54 A 3 1
55 B 3 2
Notes : No. of rows in Table 1 and 2 are not the same.
Thanks
Use a derived table to get the distinct values from table1 and simply join to table 2 and use aggregation.
The issue you have is you have a M:M relationship between table1 and table2. You need it to be a 1:M for the summations to be accurate. Thus we derive t1 from table1 by using a select distinct to give us the unique records in the 1:M relationship (assuming specs are same for each ID)
SELECT T1.ID, T1.Spec, Sum(T2.Dol1) as Dol1, sum(T2.Dol2) as Dol2
FROM (SELECT distinct ID, spec
FROM table1) T1
INNER JOIN table2 T2
on t2.ID = T1.ID
GROUP BY T1.ID, T1.Spec
This does assume you only want records that exist in both. Otherwise we may need to use an (LEFT, RIGHT, or FULL) outer join; depending on desired results.
I can't really see your data, but you might want to try:
SELECT DISTINCT ID
FROM TblOne
UNION ALL
SELECT DISTINCT ID, SUM(Dol)
FROM TblTwo
GROUP BY ID
Pre-aggregate table 2 and then join:
select t1.id, t1.spec, t2.dol1, t2.dol2
from (select t2.id, sum(dol1) as dol1, sum(dol2) as dol2
from table2 t2
group by t2.id
) t2 join
(select distinct t1.id, t1.spec
from table1 t1
) t1
on t1.id = t2.id;
For your data examples, you don't need to pre-aggregate table 2. This gives the correct sums -- albeit in multiple rows -- if table1 has multiple specs for a given id.

SQL select 1 to many within the same row

I have a table with 1 record, which then ties back to a secondary table which can contain either no match, 1 match, or 2 matches.
I need to fetch the corresponding records and display them within the same row which would be easy using left join if I just had 1 or no matches to tie back, however, because I can get 2 matches, it produces 2 records.
Example with 1 match:
Select T1.ID, T1.Person1, T2.Owner
From T1
Left Join T2
ON T1.ID = T2.MatchID
Output
ID Person1 Owner1
----------------------
1 John Frank
Example with 2 match:
Select T1.ID, T1.Person1, T2.Owner
From T1
Left Join T2
ON T1.ID = T2.MatchID
Output
ID Person1 Owner
----------------------
1 John Frank
1 John Peter
Is there a way I can formulate my select so that my output would reflect the following When I have 2 matches:
ID Person1 Owner1 Owner2
-------------------------------
1 John Frank Peter
I explored Oracle Pivots a bit, however couldn't find a way to make this work. Also explored the possibility of using left join on the same table twice using MIN() and MAX() when fetching the matches, however I can only see myself resorting this as a "no other option" scenario.
Any suggestions?
** EDIT **
#ughai - Using CTE does address the issue to some extent, however when attempting to retrieve all of the records, the details derived from this common table isn't showing any records on the LEFT JOIN unless I specify the "MatchID" (CASE_MBR_KEY) value, meaning by removing the "where" clause, my outer joins produce no records, even though the CASE_MBR_KEY values are there in the CTE data.
WITH CTE AS
(
SELECT TEMP.BEAS_KEY,
TEMP.CASE_MBR_KEY,
TEMP.FULLNAME,
TEMP.BIRTHDT,
TEMP.LINE1,
TEMP.LINE2,
TEMP.LINE3,
TEMP.CITY,
TEMP.STATE,
TEMP.POSTCD,
ROW_NUMBER()
OVER(ORDER BY TEMP.BEAS_KEY) R
FROM TMP_BEN_ASSIGNEES TEMP
--WHERE TEMP.CASE_MBR_KEY = 4117398
)
The reason for this is because the ROW_NUMBER value, given the amount of records won't necessarily be 1 or 2, so I attempted the following, but getting ORA-01799: a column may not be outer-joined to a subquery
--// BEN ASSIGNEE 1
LEFT JOIN CTE BASS1
ON BASS1.CASE_MBR_KEY = C.CASE_MBR_KEY
AND BASS1.R IN (SELECT min(R) FROM CTE A WHERE A.CASE_MBR_KEY = C.CASE_MBR_KEY)
--// END BA1
--// BEN ASSIGNEE 2
LEFT JOIN CTE BASS2
ON BASS2.CASE_MBR_KEY = C.CASE_MBR_KEY
AND BASS2.R IN (SELECT MAX(R) FROM CTE B WHERE B.CASE_MBR_KEY = C.CASE_MBR_KEY)
--// END BA2
** EDIT 2 **
Fixed the above issue by moving the Row number clause to the "Where" portion of the query instead of within the JOIN clause. Seems to work now.
You can use CTE with ROW_NUMBER() with 2 LEFT JOIN OR with PIVOT like this.
SQL Fiddle
Query with Multiple Left Joins
WITH CTE as
(
SELECT MatchID,Owner,ROW_NUMBER()OVER(ORDER BY Owner) r FROM t2
)
select T1.ID, T1.Person, t2.Owner as Owner1, t3.Owner as Owner2
FROM T1
LEFT JOIN CTE T2
ON T1.ID = T2.MatchID AND T2.r = 1
LEFT JOIN CTE T3
ON T1.id = T3.MatchID AND T3.r = 2;
Query with PIVOT
WITH CTE as
(
SELECT MatchID,Owner,ROW_NUMBER()OVER(ORDER BY Owner) R FROM t2
)
SELECT ID, Person,O1,O2
FROM T1
LEFT JOIN CTE T2
ON T1.ID = T2.MatchID
PIVOT(MAX(Owner) FOR R IN (1 as O1,2 as O2));
Output
ID PERSON OWNER1 OWNER2
1 John Maxwell Peter
If you know there are at most two matches, you can also use aggregation:
Select T1.ID, T1.Person1,
MIN(T2.Owner) as Owner1,
(CASE WHEN MIN(t2.Owner) <> MAX(t2.Owner) THEN MAX(t2.Owner) END) as Owner2
From T1 Left Join
T2
on T1.ID = T2.MatchID
Group By t1.ID, t1.Person1;

Joining two columns but keeping multiple instances in SQL

I am using SQL 2008 and am having a problem.
I have 3 different tables and here is a sample of my code.
SELECT DISTINCT Name Age
FROM Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
This returns something like this:
Name Age
tom 12
ben 23
ian 12
I have another query
SELECT Name
FROM Table3
This returns this:
ian 12
ian 12
ian 12
I want to verify that if a name and age are in name from the first query and is in the second query Table3.name it will return something like this:
ian 12
ian 12
ian 12
I have been trying Join and Union on these two columns but so far have been only been able to get it to return. Any suggestions?
ian 12
This might be able to be simplified (need to see your table structures and sample data), but given your queries, a subquery should work for you:
SELECT T3.Name, T3.Age
FROM Table3 T3
JOIN (
SELECT DISTINCT Name, Age
FROM Table1
LEFT JOIN Table2
ON Table1.ID = Table2.ID
) T ON T3.Name = T.Name AND T3.Age = T.Age
SQL Fiddle Demo
First you pronounce your problem - you want to get all records for which combination of Name and Age exists in recordset of distinct Name and Age from join. Then you use power of declarative language and a little of CTE to get your solution:
;with CTE as (
select distinct Name, Age
from Table1 as T1
inner join Table2 as T2 on T2.ID = T1.ID
)
select *
from Table3 as T3
where exists (select * from CTE as C where C.Name = T3.Name and C.Age = T3.Age)
SQL FIDDLE EXAMPLE to fiddle with query

How to replace fetched values with another column while querying with SQL Server 2008 R2

Alright let me explain my question with example
We have 1 table
This table contains
Id
Name
Number
Now example
1 House 4
2 Hospital 3
3 Airport 1
4 Station 2
Now when fetching as select * from table
I want to replace third column number values with that number representing Name
So example of fetching
1 House Station
2 Hospital Airport
3 Airport House
4 Station Hospital
How can i do this ? thank you
select t1.id,
t1.name,
t2.name as name2
from your_table t1
left join your_table t2 on t1.number = t2.id
You can join the same table twice to replace the number with the name. The on contidion in the join matches the table again and then you can select the name from that table (t2)
SQLFiddle Example
You can do this with an explicit join:
select t.id, t.name, t2.name as otherName
from t left outer join
t t2
on t2.number = t.id