SQL SELECT Data from other table based on column value - sql

Gurus,
I have a table like below
Id Name Source Value
1 a Dx C
2 b Rx G
3 C Tx H
I have 3 other tables like T1,T2 and T3 with structure as below. Based on "Source" column in parent table, I need to fetch "Data column" and show as result. If multiple records match need all record as comma-seperated
T1
Id Data
Dx 123
DX 011
T2
Id Data
Rx 456
Rx 022
T3
Id Data
Tx 789
I need Output as in T-SQL
Id Name Source Value Data
1 a Dx C 123,011
2 b Rx G 456 ,022
3 C Tx H 789
I tried with Case when but not successful. Need inputs

Try this:
DECLARE #t TABLE(ID INT, Name CHAR(1), Source CHAR(2), Value CHAR(1))
DECLARE #t1 TABLE(ID CHAR(2), Data NVARCHAR(20))
DECLARE #t2 TABLE(ID CHAR(2), Data NVARCHAR(20))
DECLARE #t3 TABLE(ID CHAR(2), Data NVARCHAR(20))
INSERT INTO #t VALUES
(1, 'a', 'Dx', 'C'),
(2, 'b', 'Rx', 'G'),
(3, 'c', 'Tx', 'H')
INSERT INTO #t1 VALUES('Dx', '1231')
INSERT INTO #t1 VALUES('Dx', '1232')
INSERT INTO #t1 VALUES('Dx', '1233')
INSERT INTO #t2 VALUES('Rx', '4561')
INSERT INTO #t2 VALUES('Rx', '4562')
INSERT INTO #t3 VALUES('Tx', '789')
SELECT t.ID ,
t.Name ,
t.Source ,
t.Value ,
COALESCE(c1.Data1, c2.Data2, c3.Data3) AS Data
FROM #t t
OUTER APPLY (SELECT STUFF((SELECT ',' + Data
FROM #t1 t1 WHERE t.Source = t1.ID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') AS Data1) c1
OUTER APPLY (SELECT STUFF((SELECT ',' + Data
FROM #t2 t2 WHERE t.Source = t2.ID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') AS Data2) c2
OUTER APPLY (SELECT STUFF((SELECT ',' + Data
FROM #t3 t3 WHERE t.Source = t3.ID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') AS Data3) c3
Output:
ID Name Source Value Data
1 a Dx C 1231,1232,1233
2 b Rx G 4561,4562
3 c Tx H 789
Version with CASE expression:
SELECT t.ID ,
t.Name ,
t.Source ,
t.Value ,
o.Data
FROM #t t
OUTER APPLY ( SELECT CASE t.Source
WHEN 'Dx' THEN STUFF((SELECT
',' + Data
FROM #t1 t1
WHERE t.Source = t1.ID
FOR XML PATH('') ,
TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
WHEN 'Rx' THEN STUFF((SELECT
',' + Data
FROM #t2 t2
WHERE t.Source = t2.ID
FOR XML PATH('') ,
TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
WHEN 'Tx' THEN STUFF((SELECT
',' + Data
FROM #t3 t3
WHERE t.Source = t3.ID
FOR XML PATH('') ,
TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
END AS DATA
) o

you don't need to case, use nested ISNULLs or COALESCE and left outer joins:
Select tbl.Id, tbl.Name, tbl.Source, tbl.value,
isnull(isnull(T1.data,T2.data),T3.data) as data
from table tbl
left outer join T1 on tbl.Source = T1.Id
left outer join T2 on tbl.Source = T2.Id
left outer join T3 on tbl.Source = T3.Id

Related

Progress 12.2 - Concat rows with same ID

I use the database Progress 12.2 and I want to group rows with same id
For example I have
ID Code
1 PB
1 RO
And I want :
ID Code
1 PB, RO
This is my request :
SELECT id, code FROM table WHERE table.id = 1
I tried String_agg, Group_concat ... but nothing works. Anyone has an idea ?
Regards,
You can use someting like that;
DECLARE #TBL TABLE (ID Int, Code nvarchar(5))
INSERT INTO #TBL values (1 ,'PB'),(1 ,'RO')
SELECT DISTINCT
T1.ID,
CONCAT_STRING = STUFF((
SELECT ',' + T2.Code
FROM #TBL T2
WHERE T2.ID = T1.ID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM #TBL T1
The result will be like this;

How to group a table, at the same time saving all column values in each group to a single column as comma-separated values

Please see the following SQL code.
Declare #LookUp table (id int,val varchar(12))
insert into #LookUp values (1,'A'),(1,'D'),(1,'X'),(2,'B'),(2,'F')
Declare #summary table (id int,val varchar(2000))
------------------------------
Declare #value varchar(30)
Declare #start int = 1, #end int = (Select count(Distinct id) from #LookUp)
While #start <= #end
Begin
Set #value = ''
Select #value = #value + '|' + val From #LookUp Where id = #start
Insert into #summary
Select #start,Right(#value,Len(#value)-1)
Set #start = #start + 1
End
Select * From #summary
With the following query, I am grouping based on Id, and making the values with in a group, as comma-separated values.
Input:
Output:
I have done this using a loop, which is not performing very well when it comes to large amount of data.
Can we do this avoiding a loop?
Note: Assume that #lookup.id is continuous.
INSERT #summary(id, val)
SELECT
t.id,
STUFF((
select '|' + [val]
from #LookUp t1
where t1.id = t.id
for xml path(''), type
).value('.', 'varchar(max)'), 1, 1, '') [values]
FROM #LookUp t
GROUP BY t.id
Try this..
Declare #LookUp table (id int,val varchar(12))
insert into #LookUp values (1,'A'),(1,'D'),(1,'X'),(2,'B'),(2,'F')
select
id,
val =
stuff((
select
'| ' + t2.val
from #LookUp t2
where
t2.id = t1.id
group by t2.val
for xml path(''), type).value('.', 'varchar(max)'
), 1, 2, '')
from #LookUp t1
GROUP BY t1.id
Declare #LookUp table (id int,val varchar(12))
insert into #LookUp values (1,'A'),(1,'D'),(1,'X'),(2,'B'),(2,'F');
WITH A AS
(
SELECT DISTINCT id
FROM #LookUp
)
SELECT
A.id,
STUFF
(
(
SELECT ',' + val
FROM #LookUp B
WHERE B.id = A.id
FOR XML PATH('')
),
1, 1, ''
) AS val
FROM A
Declare #LookUp table (id int,val varchar(12))
insert into #LookUp values (1,'A'),(1,'D'),(1,'X'),(2,'B'),(2,'F')
SELECT DISTINCT a.id, stuff((select '|' + val
from #LookUp c
where c.id = a.id
for xml path('')),1,1,'') as vall
FROM #LookUp a
I'll add a solution based on a recursive common table expression. With small modifications it should work in DB2 too (you have to change the row_number() function to rownumber() and how the concatenation works in the second list (use || instead of the concat function).
DECLARE #LookUp TABLE (id int, val varchar(12))
INSERT INTO #LookUp VALUES (1,'A'),(1,'D'),(1,'X'),(2,'B'),(2,'F')
;WITH
list1(rn, id, val) AS
(
SELECT row_number() OVER (PARTITION BY id ORDER BY id), id, val
FROM #LookUp
),
list2 (id, val, idx) AS
(
SELECT id, val, 1
FROM list1
WHERE rn = 1
UNION ALL
SELECT
list2.id,
CAST(CONCAT(list2.val, ' | ', list1.val) AS varchar(12)),
list2.idx + 1
FROM list2
JOIN list1 ON list2.id = list1.id
WHERE list2.idx + 1 = list1.rn
)
SELECT l2.id, l2.val
FROM list2 l2
JOIN (SELECT id, MAX(rn) maxid FROM list1 GROUP BY id) a
ON l2.id = a.id AND l2.idx = a.maxid
ORDER BY l2.id
This outputs:
id val
1 A | D | X
2 B | F

how to make comma separated values

This is my table structure
create table #t(PK int,col1 varchar(10),col2 varchar(10))
insert into #t values(1,'A','a'),(2,'B','b'),(3,'C','c'),(4,'A','d'),(5,'A','e'),(6,'B','f'),(88,'F','l'),(7,'C','g'),(8,'C','h'),(9,'D','k')
output column has to look like this
col1 col2
A a,d,e
B b,f
C c,g,h
D k
F l
How'd i get such an output ?
drop table #t
create table #t(PK int,col1 varchar(10),col2 varchar(10))
insert into #t values(1,'A','a'),(2,'B','b'),(3,'C','c'),(4,'A','d'),(5,'A','e'),(6,'B','f'),(88,'F','l'),(7,'C','g'),(8,'C','h'),(9,'D','k')
select col1,SUBSTRING(d.col2,1,len(d.col2)-1)col2
from
(
select distinct col1 from #t
)a
cross apply(
select [col2]+',' from #t B where A.col1=B.col1
for xml path('')
)d (col2)
DEMO
Try this
select distinct t.[col1],
STUFF((SELECT distinct ', ' + t1.col2
from yourtable t1
where t.[col1] = t1.[col1]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') department
from yourtable t;
Fiddle Demo

SQL query to split a column based on hardcoded values

I have a table eg assume this setup
table MyTable has various columns Id, UserId, col1, col2 col3 including column called Stuff.
I want to output certain Columns from MyTable with a query
but i want to split the 'Stuff' column such that 2 new columns are shown in the query
I can define the categories hardcoded, im not sure how this can be represented in sql
Categoy1 = "alpha, bravo, delta, gamma';
Categoy2 = "charlie, echo, hotel';
MyTable
ID | UserID | Stuff | Other Cols....
----------------------------------------------------------
1 1 alpha
2 2 hotel
3 1 charlie
4 1 echo
5 1 gamma
6 2 bravo
7 2 delta
i want the select query to show
UserId | Category1 | Catergory2
----------------------------------------------------------
1 alpha, gamma charlie, echo
---------------------------------------------------------
2 bravo, delta hotel
----------------------------------------------------------
i.e produce 2 columns split based on whether the stuff column contains an item from category1 or category2
based on a distinct userId the categories content can be comma separated as hown above
Please can you show how this can be done
Hope this makes sense.
Thanks
You can use the xml extensions to concatenate your strings, then just hard code the categories into each subquery:
CREATE TABLE #T (ID INT, UserID INT, [Stuff] VARCHAR(300))
INSERT #T VALUES
(1, 1, 'alpha'),
(2, 2, 'hotel'),
(3, 1, 'charlie'),
(4, 1, 'echo'),
(5, 1, 'gamma'),
(6, 2, 'bravo'),
(7, 2, 'delta');
SELECT UserID,
[Category1] = STUFF(( SELECT ', ' + [Stuff]
FROM #T t2
WHERE [Stuff] IN ('alpha', 'bravo', 'delta', 'gamma')
AND t.UserID = t2.UserID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, ''),
[Category2] = STUFF(( SELECT ', ' + [Stuff]
FROM #T t2
WHERE [Stuff] IN ('charlie', 'echo', 'hotel')
AND t.UserID = t2.UserID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM ( SELECT DISTINCT UserID
FROM #T
) t
Example on SQL Fiddle
You could define your categories at the start in a CTE (Categories) for improved readibility:
WITH Categories AS
( SELECT Category, Name
FROM (VALUES
(1, 'alpha'),
(1, 'bravo'),
(1, 'delta'),
(1, 'gamma'),
(2, 'charlie'),
(2, 'echo'),
(2, 'hotel')
) t (Category, Name)
), Data AS
( SELECT UserID, [Stuff], Category
FROM T
INNER JOIN Categories c
ON c.Name = T.[Stuff]
)
SELECT UserID,
[Category1] = STUFF(( SELECT ', ' + [Stuff]
FROM Data t2
WHERE Category = 1
AND t.UserID = t2.UserID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, ''),
[Category2] = STUFF(( SELECT ', ' + [Stuff]
FROM Data t2
WHERE Category = 2
AND t.UserID = t2.UserID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
FROM ( SELECT DISTINCT UserID
FROM T
) t
Example on SQL Fiddle
My try, the technique I learned from Stack Overflow!... Please check:
DECLARE #Categoy1 NVARCHAR(MAX) = 'alpha, bravo, delta, gamma',
#Categoy2 NVARCHAR(MAX) = 'charlie, echo, hotel'
SELECT
UserID,
STUFF((SELECT ', ' + display_term
FROM sys.dm_fts_parser('"'+ ',' + #Categoy1 + '"', 1033, NULL, 0) INNER JOIN
YourTable T on display_term=[Stuff]
WHERE T.UserID= x.UserID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '') Category1,
STUFF((SELECT ', ' + display_term
FROM sys.dm_fts_parser('"'+ ',' + #Categoy2 + '"', 1033, NULL, 0) INNER JOIN
YourTable T on display_term=[Stuff]
WHERE T.UserID= x.UserID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '') Category2
FROM YourTable x
GROUP BY UserID

Help with TSQL join query

Based on below 2 tables
declare #t1 table
(
Id int,
Title varchar(100),
RelatedId int
)
insert into #t1 values(1,'A',2)
insert into #t1 values(1,'A',3)
declare #t2 table
(
Id int,
Title varchar(100)
)
insert into #t2 values
(2,'B'),
(3,'C')
I am trying to get the below output
Id Title RelatedItems
---------------------------------
1 A 2 (B), 3 (C)
I tried the following:
select t1.Id,t1.Title, cast(t2.Id as varchar) + ' (' + t2.Title + ')' from #t1 as t1
left outer join #t2 as t2
on t1.RelatedId=t2.Id
But that gives 2 different rows. I want just one row with the data combined in the third column (as shown above). Pls. suggest.
Use:
SELECT DISTINCT
b.id,
b.title,
STUFF((SELECT ','+ CAST(t2.id AS VARCHAR(100)) + ' ('+ t2.title +')'
FROM t2
JOIN t1 a ON a.relatedid = t2.id
WHERE a.id = b.id
FOR XML PATH('')), 1, 1, '')
FROM t1 b