TSQL - create columns based on field values and duplicate rows - sql

in tsql how can I turn this sample table:
ID FIELDNO ROWNO VALUE
ABC 2 1 Cat1Val1
ABC 2 2 Cat1Val2
ABC 2 3 Cat1Val3
ABC 3 1 Cat2Val1
ABC 3 2 Cat2Val2
ABC 5 1 Cat3Val1
to a table that will create three columns based on the fieldno and duplicate the rows so that it lists all possible variations of whatever fieldno has the highest rowNo?
So fieldno 2 will become CAT1, 3 -> CAT2 and 5 -> CAT3
Expected result:
ID CAT1 CAT2 CAT3
ABC Cat1Val1 Cat2Val1 Cat3Val1
ABC Cat1Val1 Cat2Val2 Cat3Val1
ABC Cat1Val2 Cat2Val1 Cat3Val1
ABC Cat1Val2 Cat2Val2 Cat3Val1
ABC Cat1Val3 Cat2Val1 Cat3Val1
ABC Cat1Val3 Cat2Val2 Cat3Val1
I could then use this as a base to join with other tables.
Here's a fiddle with more data.
I've tried to create some CASE WHEN clauses but I think this is not going to work.
Hope you can show me a way how this can be solved.
Thank you.

This seems a bit unorthodox, but this should do it for you if I understood the problem correctly:
SELECT d1.id, d1.value Cat1, d2.value Cat2, d3.value Cat3
FROM Docs d1
INNER JOIN Docs d2 ON d2.id = d1.id AND d2.rowNo = d1.rowNo AND d2.fieldNo = 3
INNER JOIN Docs d3 ON d3.id = d2.id AND d3.rowNo = d1.rowNo AND d3.fieldNo = 5
AND d1.fieldNo = 2
This solution of course expects values will exist for each column.
Revised answer...
If the third join and only the third join (Docs.fieldNo = 5) is optional, you can do something like this:
SELECT
d2.id,
d2.value Cat1,
d3.value Cat2,
d5.value Cat3
FROM
(SELECT 2 fieldNo2, 3 fieldNo3, 5 fieldNo5) f
INNER JOIN Docs d2 ON d2.fieldNo = f.fieldNo2
INNER JOIN Docs d3 ON d3.fieldNo = f.fieldNo3 and d3.rowNo = d2.rowNo and d3.id = d2.id
LEFT JOIN Docs d5 ON d5.fieldNo = f.fieldNo5 and d5.rowNo = d2.rowNo and d5.id = d2.id
I've revised the rest of the query so that hopefully what it's doing is a little clearer.
Here are some answers on joins which you may find helpful: What is the difference between "INNER JOIN" and "OUTER JOIN"?

I have tried this in an access database:
replace myvalue with value (value is a reserved word in access)
I called the table test so replace it with your tablename.
SELECT test.id, test.myValue AS cat1, test_1.[myValue] AS cat2, test_2.myValue AS cat3
FROM test, test AS test_1, test AS test_2
WHERE (((test.myValue) Like "cat1*")
AND ((test_1.[myValue]) Like "cat2*")
AND ((test_2.myValue) Like "cat3*"))
ORDER BY test.myValue, test_1.[myValue], test_2.myValue;

Related

Join using 2 'alternative' columns from one table

I have 2 large tables like bellow in Teradata. I need to join them so that:
all records from Table A are kept - like A left join B
join is on A.client_id=B.client_id_1
but if B.client_id_1 is null, it can join on A.client_id=B.client_id_2
Table A
client_id
details_a
1
abc
2
def
3
ghi
4
jkl
Table B
client_id_1
client_id_2
details_b
1
null
123
null
2
456
3
3
789
The result should be like:
client_id
details_a
client_id_1
client_id_2
details_b
1
abc
1
null
123
2
def
null
2
456
3
ghi
3
3
789
4
jkl
null
null
null
The tables are large and the join is part of a larger script (other joins using Table B)
I tried something like
Table A LEFT JOIN Table B
ON (A.client_id = B.client_id_1 OR A.client_id = B.client_id_2)
But the result was product join that never finished.
I also want to avoid two left joins (on B.client_id_1 and on B.client_id_2) as it would result in having all columns from Table B twice. And the Table B is further used in following joins. Plus client_id=3 would have two records.
Any idea? And what is wrong with the JOIN using OR above?
Thanks, R.
You can use case statement:
Table A LEFT JOIN Table B
ON (A.client_id = case when B.client_id_1 is null then B.client_id_2 else B.client_id_1 end)
oR Coalesce:
Table A LEFT JOIN Table B
ON (A.client_id = Coalesce(B.client_id_1 ,B.client_id_2 ))
If B.client_id_1 is not null then Coalesce(B.client_id_1 ,B.client_id_2 ) will return B.client_id_1 but if it's null then the condition will return B.client_id_2 .

Sybase SQL select statement to collapse and condense rows by an ID

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

Compare 2 tables in sql

I have two tables, A1 and A2. I want to compare these two tables. I tried inner join but it doesn't give the required result.
These are the data in these tables,
Table A1
No. Address
1 abc
1 abc
1 def
1 def
Table A2
No. Address
1 def
1 abc
1 abc
1 def
These two tables can only be joined by using No. column. So if I use INNER JOIN it gives 16 rows. I don't want that, I want only 4 rows to be displayed. This should be the output:
No. Address eq
1 abc #
1 abc *
1 abc #
1 abc #
Last column is displayed if address in A1 is equal to A2
Search for records that exist in A1 table but not in A2 table:
SELECT * FROM A1 WHERE NOT EXISTS (SELECT * FROM A2 WHERE A2.Id = A1.Id)
try to use case
select case when tablea1.address=tablea2.address then '*'
else '#' end as eq from tablea1 inner join tablea2 on tablea1.=tablea2.
hope it helps you.

JOIN multiple fields to one field

dbname : table_name
table : abc
Remark1 Remark2 Remark3 Remark4 Remark5
1 2 3 4 5
table : xyz
Kod_type description
1 xxxx
2 yyyy
3 zzzz
4 aaaa
5 bbbb
how do i join Remark1,Remark2,Remark3,Remark4,Remark5 with kod_type?
Use AND Condition with On clause while joining two tables.
If you wants to match all remarks column should match to Kod_Type
SELECT abc.*,
xyz.*
FROM abc
INNER JOIN xyz
ON abc.Remark1 = xyz.Kod_Type
AND abc.Remark2 = abc.Remark1
AND abc.Remark3 = abc.Remark1
AND abc.Remark4 = abc.Remark1
AND abc.Remark5 = abc.Remark1
If you want the record in which any of the remarks column match to Kod_Type
SELECT abc.*,
xyz.*
FROM abc
INNER JOIN xyz
ON abc.Remark1 = xyz.Kod_Type
OR abc.Remark2 = xyz.Kod_Type
OR abc.Remark3 = xyz.Kod_Type
OR abc.Remark4 = xyz.Kod_Type
OR abc.Remark5 = xyz.Kod_Type
You do it the same way you will do normally -
SELECT ABC.*, XYZ.* FROM XYZ, ABC
WHERE
XYZ.KOD_TYPE=ABC.REMARK1
AND XYZ.KOD_TYPE=ABC.REMARK2
AND XYZ.KOD_TYPE=ABC.REMARK3
AND XYZ.KOD_TYPE=ABC.REMARK4
AND XYZ.KOD_TYPE=ABC.REMARK5
If you need query where any one remark matches -
SELECT ABC.*, XYZ.* FROM XYZ, ABC
WHERE
XYZ.KOD_TYPE=ABC.REMARK1
OR XYZ.KOD_TYPE=ABC.REMARK2
OR XYZ.KOD_TYPE=ABC.REMARK3
OR XYZ.KOD_TYPE=ABC.REMARK4
OR XYZ.KOD_TYPE=ABC.REMARK5
The question is not very clear, but I think something like this was intended.
SELECT COALESC(d1.description, '') as description1
, COALESC(d2.description, '') as description2
, COALESC(d3.description, '') as description3
, COALESC(d4.description, '') as description4
, COALESC(d5.description, '') as description5
FROM abc
LEFT JOIN xyz d1 ON d1.kod_type=abc.remark1
LEFT JOIN xyz d2 ON d2.kod_type=abc.remark2
LEFT JOIN xyz d3 ON d3.kod_type=abc.remark3
LEFT JOIN xyz d4 ON d4.kod_type=abc.remark4
LEFT JOIN xyz d5 ON d5.kod_type=abc.remark5
;

MySql Select Query

I have 2 tables like this
Table 1
Id f1 f2
1 ABC red,green
2 DEF blue,yellow
Table 2
id color value
1 red r
2 green g
3 blue b
4 yellow y
How Can I get result like this
f1 f2 values
ABC red,green r,g
DEF blue,yellow b,y
Thanks in Advance
Use the GROUP_CONCAT function:
SELECT t1.f1,
t1.f2,
GROUP_CONCAT(t2.value) AS values
FROM TABLE_1 t1
JOIN TABLE_2 t2 ON FIND_IN_SET(t2.color, t1.f2)
GROUP BY t1.f1, t1.f2
Can you adjust the schema? I think it would benefit if you had a mapping table of whatever ABC is to the colors.
EG:
mapping_table
------------
id table1_id table2_id
1 1 1
2 1 2
That way you can easily do a JOIN.