I need help constructing an SQL statement with Sybase to collapse rows linked by three columns, ID, Name and DEPT. I have one table TABLE1:
ID NAME DEPT CAT
1 ghi P
1 CV G
2 abc P
2 IT G
2 HC G
3 def P
3 jkl P
3 ENT G
3 MC G
The CAT column means category. The P column means person. The G column means group.
ID can be person(NAME) as well as group(DEPT).
If ID(1) is associated with a person(NAME) as well as a group(DEPT) then I want to update the person(NAME) row to have DEPT name as well and then delete the group(DEPT) row. If ID(2) is associated with one person(NAME) and more than one DEPT(group) then I want to have two rows for that NAME. If ID(3) contains two different NAME and two different DEPT then I want separate rows for each NAME and DEPT as shown below:
Below is the expected output I want:
ID NAME DEPT CAT
1 ghi CV P
2 abc IT P
2 abc HC P
3 def ENT P
3 def MC P
3 jkl ENT P
3 jkl MC P
I would like an SQL statement that returns the above rows from TABLE1. Is it possible?
This might work for you.
SELECT t1.ID, t1.NAME, t2.DEPT, t1.CAT
FROM TABLE1 AS t1
INNER JOIN TABLE1 AS t2 ON (t1.ID = t2.ID)
WHERE t2.DEPT IS NOT NULL AND t1.NAME IS NOT NULL
Related
I'm doing an inner join on a table like this:
SELECT *
FROM patient p
INNER JOIN
vaccine v
ON
p.vaccine_id = v.id
The condition f.vac_1 = mv.id might not been satisfied in the case where a person have not been vaccinated. In such case, I don't want to ignore the row, but instead of displaying the vaccine name (which is the purpose of the inner join) to display an emtpy string.
How can this be done ?
Example
Table vaccinne
id
name
1
Moderna
2
Comirnaty
3
Janssen
Table patient
id
name
vaccine_id
1
john
1
2
kermit
2
3
jessica
I'm looking for a query to produce:
id
name
vaccine_id
1
john
Moderna
2
kermit
Comirnaty
3
jessica
If I understand correctly, you want a left join starting with foo:
SELECT *
FROM foo f LEFT JOIN
vac v
ON f.vac_1 = mv.id
I'm trying to INNER JOIN 3 tables together with a PIVOT on the third table. Joining isn't an issue but PIVOT's are pretty new to me and combining them together has turned into a disaster. I'm not sure how to do the following:
Table 1
ID Mnemonic Gender
1 SKYL F
2 HANS M
Table 2
ID LastName FirstName
1 Skywalker Leia
2 Solo Han
Table 3
ID Query Response
1 a red
1 b green
1 c blue
1 d yellow
2 a black
2 b white
2 c orange
2 d purple
Final Table
ID Mnemonic Gender LastName FirstName Query_a Query_b
1 SKYL F Skywalker Leia red green
2 HANS M Solo Han black white
One area I know I'm having issues is that I dont want all the 'Responses' from Table 3, just when the 'Query' column is 'a' or 'b'. I might end up creating 2 new tables to replace Table 3, so I can get rid of the PIVOT all together and just INNER JOIN the 4 tables.
I followed along with SQL server join tables and pivot but could not get it to work with more than 2 tables with not all Queries needed to be PIVOT'ed.
you only need to Pivot table 3 - so just pivot Table 3 with a CTE expression as below and then join the result with Table 1 and 2
WITH pivot_cte
(
id,
query_a,
query_b
)
AS
-- Define the CTE query.
(
SELECT *
FROM (
SELECT Id, a query_a,
b query_b
FROM table3 ) table3 PIVOT ( Max(response) FOR query IN ([a],
[b]) ) piv;)
SELECT *
FROM pivot_cte
JOIN table1
ON table1.id=pivot_cte.id
JOIN table2
ON table2.id=pivot_cte.id
I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D
Okay, I am trying to write a query from a poor table structure.
Below is something that I want to achieve:
Table 1: List of Items
T1C1 T1C2
A Fred
B Bart
C Carl
Table 2: Second list of Items
T2C1 T2C2
1 Chocolate
2 Cake
3 Pie
4 Fish
5 Pizza
Table 3: Joining table
T3C1 T3C2 T3C3
1 A Y
4 A Y
5 A N
1 B N
2 B Y
5 B Y
1 C Y
2 C N
3 C Y
Result
Select query based on a person in Table 1.
However if the value is not in Table 3 then R1C4 should default to N
R1C1 R1C2 R1C3 R1C4
1 Chocolate A Y
2 Cake A N
3 Pie A N
4 Fish A Y
5 Pizza A N
I've assumed a few details to come up with the following:
DECLARE #UserId CHAR
SET #UserId = 'A'
SELECT T2.T2C1 AS R1C1,
T2.T2C2 AS R1C2,
COALESCE(T3.T3C2, #UserId) AS R1C3,
COALESCE(T3.T3C3, 'N') AS R1C4
FROM Table2 AS T2
LEFT JOIN Table3 AS T3 ON T3.T3C1 = T2.T2C1 AND T3.T3C2 = #UserId
Assumption: example output is for user Fred.
To ensure that we see all entries from Table2 we use a LEFT JOIN on the link table (Table3).
We have to COALESCE the values for the two records that don't exist in the link table.
Note that this only works if we filter to one user, as per the expected output.
View my SQL Fiddle for full example.
declare #filter varchar(1)
select #filter= T1C1 from Table_1 where T1C2='Fred';
with CteResult (R1C1,R1C2,R1C3,R1C4)as
(select T2C1 as R1C1,T2C2 as R1C2,T3C2 as R1C3, T3C3 as R1C4 from table_2 A
inner join Table_3 B on T2C1 =T3C1
where T3C2=#filter)
select T2C1 as R1C1,T2C2 as R1C2,coalesce(R1C3,#filter) as R1C3,
case when R1C4 is null then 'N' else R1C4 end R1C4
from table_2 A left outer join CteResult B
on B.R1C1=A.T2C1
I would like to know what's the logic for multiple joins (for example below)
SELECT * FROM B returns 100 rows
SELECT B.* FROM B LEFT JOIN C ON B.ID = C.ID returns 120 rows
As I know using left join will returns any matching data from the left table which is B if data are found for both table. But how come when using left join, it returns more data than table B itself?
What am I do wrong or misunderstood here? Any guidance are very appreciated. Thanks in advance.
Let be table B:
id
----
1
2
3
Let be table C
id name
------------
1 John
2 Mary
2 Anne
3 Stef
Any id from b is matched with ids from c, then id=2 will be matched twice. So a left join on id will return 4 rows even if base table B has 3 rows.
Now look at a more evil example:
Table B
id
----
1
2
2
3
4
table C
id name
------------
1 John
2 Mary
2 Anne
3 Stef
Every id from b is matched with ids from c, then first id=2 will be matched twice and second id=2 will be matched twice so the result of
select b.id, c.name
from b left join c on (b.id = c.id)
will be
id name
------------
1 John
2 Mary
2 Mary
2 Anne
2 Anne
3 Stef
4 (null)
The id=4 is not matched but appears in the result because is a left join.
Look at the following example :
B = {1,2}
C = {(1,a),(1,b),(1,c),(1,d),(1,e)}
The result of B left join C will be :
1 | a
1 | b
1 | c
1 | d
1 | e
2 | null
The number of rows in the result is definitely larger than rows in B (2).
In general the number of rows in result of B left join C is bounded by B.size + C.size and not only by B.size as you think...
As per your query it do the join to B Table with C and B table is Left Table so it will display all the records of Left table in our case it is B and related from other Table in our Case it is C.