How to join rows in some table in SQL Server? - sql

i want join some table then concatenation columns
MyTable
-------------------------------
ID RowId LangId Caption
-------------------------------
1 1 1 ڕۆشتن
2 1 2 Go
3 1 3 اذهب
4 2 1 ئاو
5 2 2 water
6 2 3 ماء
I want join concatenation Caption column ex: for RowId 1 'ڕۆشتن - Go - اذهب'
Desired output
--------------------
RowId Caption
--------------------
1 ڕۆشتن - Go - اذهب
2 ئاو- water - ماء
I seen link but can't help me

You can use string_agg():
select rowid,
string_agg(caption, ' ') within group (order by langid) as caption
from t
group by rowid;

You can use for xml for older vresion :
select r.rowid,
stuff( (select ' - '+t.caption
from table t
where t.rowid = r.rowid
order by t.LangId
for xml path('')
), 1, 1, ''
) as Caption
from (select distinct rowid from table ) r;
You can use string_agg() for newer version SQL Server 17+ :
select t.rowid,
string_agg(t.caption, ' ') within group (order by t.langid) as caption
from table t
group by t.rowid;

You can try the following query using for xml as shown below.
SELECT DISTINCT t.RowId,
STUFF((SELECT distinct ' - ' + t1.[Caption]
FROM
(
SELECT t.[RowId],
t2.Caption
FROM [TestTable] AS t
INNER JOIN [TestTable] AS t2 ON t2.[RowId] = t.[RowId]
)
t1
WHERE t.RowId = t1.RowId
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') CaptionList
FROM
(
SELECT t.[RowId],
por.Caption
FROM [TestTable] AS t
INNER JOIN [TestTable] AS por ON por.RowId = t.RowId
)t;
Here is the live db<>fiddle demo.

Try this:
SELECT DISTINCT RowID,
STUFF((SELECT DISTINCT Sub.caption +' - '
FROM #tab Sub
WHERE Sub.rowid = Main.rowid
FOR XML PATH('')), 1, 1, '') AS Caption
FROM #tab Main
I think this Query can perfectly fit for your case.

Related

using recursive function to simulate group_concat

I have a table like
ID NAME
1 STALIN
2 MERWIN
1 AMALA
1 RAYON
i want the out as
ID NAME
1 STALIN,AMALA,RAYON
2 MERWIN
How can do this using recursive function
You can do this using XML Path
SELECT ID, NAME =
STUFF((SELECT ', ' + NAME
FROM your_table b
WHERE b.ID = a.ID
FOR XML PATH('')), 1, 2, '')
FROM your_table a
GROUP BY ID
Live Demo
Follow this link and see the case 3. it explains why to use XML path over recursive cursor.
You can use FOR XML PATH to get the result:
for example:
DECLARE #EXAMPLE TABLE (ID int, NAME nvarchar(10))
INSERT #EXAMPLE VALUES (1,'STALIN'),(2,'MERWIN'),(1,'AMALA'),(1,'RAYON')
SELECT
ID,
SUBSTRING(NAME,0,LEN(NAME)) AS NAME
FROM ( SELECT DISTINCT
T1.ID,
STUFF(( SELECT DISTINCT '' + t2.NAME + ','
FROM #EXAMPLE T2
WHERE T1.ID = T2.ID
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)')
,1,0,'') NAME
FROM #EXAMPLE t1) AS info

In SQL Count number of distinct values corresponding to a same Id and DISPLAY in a same row

I am stuck on a SQL query. I have results as below in a table and have to display the final result in a report as below:
id Question
-------------
13 ABC
13 ABC
13 QWE
13 ABC
13 QWE
13 ABC
Expected result:
id Result
--------------------
13 4 ABC, 2 QWE
Can somebody please help me out? Thank you.
This requires pre-aggregation and string aggregation.
with t as (
select id, question, count(*) as cnt
from t
group by id
)
select i.id,
stuff( (select ', ' + convert(varchar(255), cnt) + ' ' + question
from t t2
where t2.id = i.id
for xml path ('')
), 1, 2, ''
) as result
from (select distinct id from t) i;
--testdata-begin
if not object_id(N'Tempdb..#T') is null
drop table #T
Go
Create table #T([id] int,[Question] nvarchar(23))
Insert #T
select 13,N'ABC' union all
select 13,N'ABC' union all
select 13,N'QWE' union all
select 13,N'ABC' union all
select 13,N'QWE' union all
select 13,N'ABC'
Go
--testdata-end
WITH cte AS (
Select id,Question,COUNT(1) AS num from #T GROUP BY id,Question
)
SELECT id,
STUFF(
(
SELECT ',' + RTRIM(b.num) + ' ' + b.Question
FROM cte b
WHERE a.id = b.id
FOR XML PATH('')
),
1,
1,
''
) AS Result
FROM cte a
GROUP BY id;

Get 3 rows data in 1 row

My records looks like:
aid cmpyname rid imgpath
1 abc 1 ~/img/aa.jpg:~/img/bb.jpg:~/img/cc.jpg:
2 abc 1 ~/img/dd.jpg:~/img/ee.jpg:~/img/ff.jpg:
3 xyz 2 ~/img/gg.jpg:~/img/hh.jpg:~/img/ii.jpg:
4 xyz 2 ~/img/jj.jpg:~/img/kk.jpg:~/img/ll.jpg:
What I want to get is displayed below - but in a single query
cmpyname rid imgpath
abc 1 ~/img/aa.jpg:~/img/bb.jpg:~/img/cc.jpg:~/img/dd.jpg:~/img/ee.jpg:~/img/ff.jpg:
xyz 2 ~/img/gg.jpg:~/img/hh.jpg:~/img/ii.jpg:~/img/jj.jpg:~/img/kk.jpg:~/img/ll.jpg:
How can I do so? I haven't provided any relationship so please keep it in mind.
Thanks and Regards
select max(cmpyname) as cmpyname, rid,
stuff((
select imgpath
from Records t1
where t1.rid = t2.rid
order by t1.aid
for xml path(''), type).value('.', 'varchar(max)'), 1, 0, ''
) as imgpath
from Records t2
group by rid;
http://sqlfiddle.com/#!18/46822/1
select distinct rid,imgpath,rid from(
select imgpath=(select imgpath + ', ' AS 'data()'
FROM tbl_Temp
where tbl_Temp.rid=rid FOR XML PATH('') )
,id,cmpyname,rid from tbl_Temp
) as temp
Something like this:
Just paste into into an empty query window and execute. Adapt to your needs...
DECLARE #tbl TABLE(aid INT, cmpyname VARCHAR(100), rid INT, imgpath VARCHAR(1000));
INSERT INTO #tbl VALUES
(1,'abc',1,'~/img/aa.jpg:~/img/bb.jpg:~/img/cc.jpg:')
,(2,'abc',1,'~/img/dd.jpg:~/img/ee.jpg:~/img/ff.jpg:')
,(3,'xyz',2,'~/img/gg.jpg:~/img/hh.jpg:~/img/ii.jpg:')
,(4,'xyz',2,'~/img/jj.jpg:~/img/kk.jpg:~/img/ll.jpg:');
SELECT DISTINCT tbl.cmpyname
,tbl.rid
,(
SELECT '' + x.imgpath
FROM #tbl AS x
WHERE x.rid=tbl.rid
FOR XML PATH('')
) AS allPaths
FROM #tbl AS tbl
SELECT DISTINCT B.cmpyname, B.rid,
(
SELECT imgpath + '' FROM tbl1 AS A WHERE (B.rid = A.rid) FOR XML PATH('')
) AS imgpath
FROM tbl1 AS B

sql server(find the count of table base on condition)

i have a table like following
RequestNo Facility status
1 BDC1 Active
1 BDC2 Active
1 BDC3 Active
2 BDC1 Active
2 BDC2 Active
i want like this
RequestNo Facilty Count
1 BDC (1,2,3) 1
2 BDC(1,2) 1
the count should display based on Status with facilty.Fcilityv should take as BDC only
Try this, (assuming that your facility is fixed 4 character code)
SELECT RequestNo, Fname + '(' + FnoList + ')' Facilty, count(*) cnt
FROM
(
SELECT distinct RequestNo,
SUBSTRING(Facility,1,3) Fname,
stuff((
select ',' + SUBSTRING(Facility,4,4)
from Dummy
where RequestNo = A.RequestNo AND
SUBSTRING(Facility,1,3) = SUBSTRING(A.Facility,1,3)
for xml path('')
) ,
1, 1, '') as FnoList
FROM Dummy A
) x
group by RequestNo, Fname, FnoList;
SQL DEMO
This doesn't put any constraints on the length of the Facility field. It strips out the chars from the beginning and the numeric numbers from the ending:
SELECT RequestNo, FacNameNumbers, COUNT(Status) as StatusCount
FROM
(
SELECT DISTINCT
t1.RequestNo,
t1.Status,
substring(facility, 1, patindex('%[^a-zA-Z ]%',facility) - 1) +
'(' +
STUFF((
SELECT DISTINCT ', ' + t2.fac_number
FROM (
select distinct
requestno,
substring(facility, 2 + len(facility) - patindex('%[^0-9 ]%',reverse(facility)), 9999) as fac_number
from facility
) t2
WHERE t2.RequestNo = t1.RequestNo
FOR XML PATH (''))
,1,2,'') + ')' AS FacNameNumbers
FROM Facility t1
) final
GROUP BY RequestNo, FacNameNumbers
And the SQL Fiddle

Comma Separated SQL Server Result Set 'JOINED' with other Columns

I have a table say ProjectMaster:
Id ProjectName
1 A
2 B
3 C
another table ProjectMeter
Id ProjectId MeterNumber
1 1 #0001
2 1 #0002
3 1 #0003
4 2 #0004
5 2 #0005
6 3 #0006
I wish to have following output
ProjectName MeterNumbers
A #0001, #0002, #0003
B #0004, #0005
C #0006
I tried this and this, but unable to solve my problem.
I cannot use a table variable.
I have a already written Stored Procedure and it brings data from many joined tables. ProjectMaster also happens to be joined in one of these tables. Now am required to fetch data from ProjectMeter, such that, each row has concatenated ProjectMeter.MeterNumber corresponding to the ProjectId in that column.
right now, I get concatenated list of all meternumbers in all the rows.
I cannot use CURSOR, TABLE variable , Temp TABLE
( I hope still something can be done to my cause)
please help.....
Try this:
SELECT projectname, STUFF((SELECT distinct ', ' + meternumber
from projectmeter m
where p.id = m.projectid
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'') MeterNumbers
from projectmaster p
See SQL Fiddle with Demo
DECLARE #ProjectMaster AS TABLE
(
ID INT IDENTITY(1, 1) ,
ProjectName VARCHAR(2)
)
DECLARE #ProjectMeter AS TABLE
(
ID INT IDENTITY(1, 1) ,
ProjectID INT ,
MeterNumber VARCHAR(50)
)
INSERT INTO #ProjectMaster
( ProjectName )
VALUES ( 'A' )
INSERT INTO #ProjectMeter
( ProjectID, MeterNumber )
VALUES ( 1, '#0001' )
INSERT INTO #ProjectMeter
( ProjectID, MeterNumber )
VALUES ( 1, '#0002' )
SELECT pMaster.ID, STUFF(( SELECT ',' + MeterNumber
FROM #ProjectMeter
FOR
XML PATH('')
), 1, 1, '') AS 'Concat Result'
FROM #ProjectMeter pMeter
INNER JOIN #ProjectMaster pMaster ON pMaster.ID = pMeter.ProjectID
GROUP BY pMaster.ID
I have used table variables here but surely you just need to drop the #'s as I have used the same table names as you have specified? Not sure if this is okay? :)
Also in MS SQL you can do it using recursive query with CTE.
Here is a SQLFiddle demo
;with t1 as (
select t.*,
cast(meternumber as varchar(max)) as m2,
0 as level
from ProjectMeter t
where not exists
(select id
from ProjectMeter l
where l.id<t.id and l.ProjectId=t.ProjectID
)
union all
select b.*,
cast(c.m2+','+b.MeterNumber as varchar(max)) as m2,
c.level+1 as level
from ProjectMeter b
inner join t1 c
on (c.id < b.id) and (b.ProjectID=c.ProjectId)
)
select pm.ProjectName as ProjectName,
t1.m2 as MeterNumbers
from t1
inner join
(select ProjectId,max(level) ml
from t1
group by ProjectId
) t2
on (t1.ProjectId=t2.ProjectID) and (t1.level=t2.ml)
left join ProjectMaster pm
on (t1.ProjectId=pm.Id)
order by t1.ProjectID