stuff(( select distinct ',',Convert(varchar(256),y.RoomPlanID)
from(
select x.RoomPlanID ,x.RoomPlanHierarchy from (select utblConfigDestRoomRates.RoomPlanID,utblMstRoomPlans.RoomPlanHierarchy
FROM utblConfigDestRoomRates inner
JOIN utblMstRoomPlans on utblConfigDestRoomRates.RoomPlanID=utblMstRoomPlans.RoomPlanId
WHERE PropertyTypeID=1
AND BusinessID='AAAA'
AND('25-Aug-2015' BETWEEN DateEffective AND DateEnd)
AND StarRank=3 group by RoomPlanHierarchy order by RoomPlanHierarchy asc
) x
--order by
-- x.RoomPlanHierarchy
)y
FOR XML PATH('')), 1, 1, '')
You can use ROW_NUMBER (Transact-SQL) function. I assume that order to x.RoomPlanHierarchy like this
stuff(( select distinct ',',Convert(varchar(256),y.RoomPlanID)
from(
select x.RoomPlanID ,x.RoomPlanHierarchy,ROW_NUMBER() OVER(ORDER BY x.RoomPlanHierarchy asc) AS Row from (select utblConfigDestRoomRates.RoomPlanID,utblMstRoomPlans.RoomPlanHierarchy
FROM utblConfigDestRoomRates inner
JOIN utblMstRoomPlans on utblConfigDestRoomRates.RoomPlanID=utblMstRoomPlans.RoomPlanId
WHERE PropertyTypeID=1
AND BusinessID='AAAA'
AND('25-Aug-2015' BETWEEN DateEffective AND DateEnd)
AND StarRank=3 group by RoomPlanHierarchy
) x
--order by
-- x.RoomPlanHierarchy
)y
FOR XML PATH('')), 1, 1, '')
--Format it in SQL
(
SELECT
stuff(
(
SELECT
'' + a.col_name ,
'' + Replace(CAST(a.pos as VARCHAR), a.pos, '') + '"'
FROM
(
SELECT
CAST (',' + db_column_name + ' AS "' + REPLACE(label_tag, '.', '_') AS nvarchar (4000) ) AS col_name,
row_number() over (partition BY RIGHT(entity, CHARINDEX('.', (REVERSE(entity)) ) - 1) ORDER BY db_column_name) AS pos
FROM
table1 AS ex
JOIN
table2 AS ef
ON
ef.col1 = ex.col1
WHERE
entity LIKE '%string%')a FOR xml path('')) , 1, 1, '' ) )
Related
Please help how to achieve data as per shown in attached image
Highlighted rows actually group on Item Number field
Thanks in advance
Following should work:
SELECT distinct ItemNumber,SUBSTRING(
(SELECT ';' + TotalItem+' x '+ItemName
FROM YourTable
where ItemNumber=c.ItemNumber
ORDER BY ItemNumber
FOR XML PATH('')),2,200000 ) AS NewDescription from YourTable c
GO
Here's one way:
SELECT
it.[Item Number]
, Values1 = STUFF(CAST((
SELECT [text()] = ', ' + CAST(it2.TotalItem AS varchar) + ' x ' + it2.ItemName
FROM dbo.Items it2
WHERE it2.[Item Number] = it.[Item Number]
FOR XML PATH(''), TYPE) AS VARCHAR(100)), 1, 2, '')
FROM (
SELECT DISTINCT [Item Number]
FROM dbo.Items
) it
You could use STRING_AGG
SELECT [Item Number], STRING_AGG (CONCAT(TotalItem,'x',ItemName), ';') as tags
FROM dbo.TableName
GROUP BY [Item Number];
SELECT t2.ItemNumber ,
STUFF(( SELECT ',' + CAST(TotalItem AS VARCHAR) + ' x ' + ItemName
FROM #MyTable t1
WHERE t1.ItemNumber = t2.ItemNumber
FOR
XML PATH('')
), 1, 1, '') AS NewDescription
FROM #MyTable t2
GROUP BY t2.ItemNumber
DEMO
I have a table like this:
I need to get output like this:
I tried to use transposing, but I am not getting someone please give idea to do this.
Creation script for table:
CREATE TABLE #T1 (
itemid int,
pack int,
UOM nvarchar(2)
)
INSERT INTO #T1 VALUES
(1,1,'EA'),
(1,10,'BX'),
(1,100,'CA'),
(2,1,'EA'),
(2,10,'RL')
If you need simple, fixed column solution, you can use:
SELECT * INTO #temp FROM
(VALUES
(1, 1, 'EA'),
(1, 10, 'BX'),
(1, 100, 'CA'),
(2, 1, 'EA'),
(2, 10, 'RL')) T(ItemId, Pack, UOM)
SELECT ItemId, MAX([1]) Pack1, MAX([U1]) UOM1, MAX([2]) Pack1, MAX([U2]) UOM1, MAX([3]) Pack1, MAX([U3]) UOM1 FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack) PackNum,
'U'+CONVERT(varchar(10), ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack)) UOMNum
FROM #temp
) T
PIVOT
(
MAX(Pack) FOR PackNum IN ([1], [2], [3])
) PPack
PIVOT
(
MAX(UOM) FOR UOMNum IN ([U1],[U2],[U3])
) PUOM
GROUP BY ItemId
If number of columns is not fixed, you must do it dynamically (see #gofr1) or:
DECLARE #count TABLE(N varchar(10))
INSERT #count
SELECT CONVERT(varchar(10), ROW_NUMBER() OVER (ORDER BY (SELECT 1)))
FROM #temp WHERE ItemId =
(
SELECT TOP 1 ItemId
FROM #temp
GROUP BY ItemId
ORDER BY COUNT(*) DESC
)
DECLARE #select varchar(MAX) = STUFF((SELECT ', MAX(['+N+']) Pack'+N+', MAX([U'+N+']) UOM'+N FROM #count FOR XML PATH('')), 1, 2, '')
DECLARE #pivot1 varchar(MAX) = STUFF((SELECT ', ['+N+']' FROM #count FOR XML PATH('')), 1, 2, '')
DECLARE #pivot2 varchar(MAX) = STUFF((SELECT ', [U'+N+']' FROM #count FOR XML PATH('')), 1, 2, '')
DECLARE #sql varchar(MAX) = '
SELECT ItemId, '+#select+' FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack) PackNum,
''U''+CONVERT(varchar(10), ROW_NUMBER() OVER (PARTITION BY ItemId ORDER BY Pack)) UOMNum
FROM #temp
) T
PIVOT
(
MAX(Pack) FOR PackNum IN ('+#pivot1+')
) PPack
PIVOT
(
MAX(UOM) FOR UOMNum IN ('+#pivot2+')
) PUOM
GROUP BY ItemId'
EXEC(#sql)
Dynamic SQL and some pivoting:
DECLARE #sql nvarchar(max),
#columns nvarchar(max)
SELECT #columns = (
SELECT DISTINCT ','+QUOTENAME('pack' + cast(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY itemid) as nvarchar(max)))+','+
QUOTENAME('UOM'+ cast(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY itemid) as nvarchar(max)))
FROM #T1
FOR XML PATH('')
)
SELECT #sql = N'
SELECT *
FROM (
SELECT itemid,
Items+rn as Items,
[Values]
FROM (
SELECT itemid,
CAST(UOM as nvarchar(max)) as UOM,
CAST(pack as nvarchar(max)) as pack,
CAST(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY (SELECT NULL)) as nvarchar(max)) as rn
FROM #T1
) as t
UNPIVOT (
[Values] FOR Items in ([UOM],[pack])
) as up
) t1
PIVOT (
MAX([Values]) FOR Items IN ('+STUFF(#columns,1,1,'')+')
) as pvt'
EXEC sp_executesql #sql
Output:
itemid pack1 UOM1 pack2 UOM2 pack3 UOM3
1 1 EA 10 BX 100 CA
2 1 EA 10 RL NULL NULL
EDIT#1
There is one more way:
DECLARE #sql nvarchar(max),
#columns nvarchar(max),
#colsrn nvarchar(max)
;WITH cte AS (
SELECT DISTINCT cast(ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY itemid) as nvarchar(max)) as rn
FROM #T1
)
SELECT #columns = (
SELECT ',MAX('+QUOTENAME('pack' + rn) +') as '+ QUOTENAME('pack' + rn) +',MAX('+
QUOTENAME('UOM'+ rn) +') as ' + QUOTENAME('UOM'+ rn)
FROM cte
FOR XML PATH('')
),
#colsrn = (
SELECT DISTINCT ',CASE WHEN rn = ' + rn +' THEN '+QUOTENAME('pack')+' ELSE NULL END as [pack'+rn+'],'
+'CASE WHEN rn = ' + rn +' THEN '+QUOTENAME('UOM')+' ELSE NULL END as [UOM'+rn+']'
FROM cte
FOR XML PATH('')
)
SELECT #sql = N'
SELECT itemid'+#columns+'
FROM (
SELECT itemid'+#colsrn+'
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY itemid ORDER BY (SELECT NULL)) as rn
FROM #T1
) as t
) s
GROUP BY s.itemid'
EXEC sp_executesql #sql
Same output.
select itemid,
max(case when seq = 1 then pack end) pack1, max(case when seq = 1 then uom end)uom1,max(case when seq = 2 then pack end) pack2, max(case when seq = 2 then uom end) uom2,
max(case when seq = 3 then pack end) pack3, max(case when seq = 3 then uom end) uom3
from
(
select itemid, pack, uom, row_number() over(partition by itemid order by itemid) seq from T1
) d
group by itemid
How to compare to String of type below
#Qstring='C,D,B,C,D,C,E,B,E,A,D,'
#Astring='C,D,C,E,D, ,E, ,E, ,A,'
and produce the string similar below.
is there method compare without using loop and temp table
Blankstring='6,8,10'
BlankCount=3
MatchingString=1,2,5,7,9
matchcount =5
You probably shouldn't do it in DB but why not:
Warning: this is sketch only and should be improved if needed.
SqlFiddleDemo
Code:
DECLARE
#Qstring NVARCHAR(100) ='C,D,B,C,D,C,E,B,E,A,D,',
#Astring NVARCHAR(100) ='C,D,C,E,D, ,E, ,E, ,A,';
DECLARE
#Qxml XML = CONVERT(XML,'<Vals><Val>' + REPLACE(LEFT(#Qstring,LEN(#Qstring)-1),',', '</Val><Val>') + '</Val></Vals>'),
#Axml XML = CONVERT(XML,'<Vals><Val>' + REPLACE(LEFT(#Astring,LEN(#Astring)-1),',', '</Val><Val>') + '</Val></Vals>');
;WITH QStringTab AS
(
SELECT
[val] = x.i.value('.', 'NVARCHAR(10)')
,[rn] = ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM #Qxml.nodes('/Vals/Val') AS x(i)
), AStringTab AS
(
SELECT
[val] = x.i.value('.', 'NVARCHAR(10)')
,[rn] = ROW_NUMBER() OVER (ORDER BY (SELECT 1))
FROM #Axml.nodes('/Vals/Val') AS x(i)
), matchcount AS
(
SELECT c = COUNT(*)
FROM QStringTab q
JOIN AStringTab a
ON q.rn = a.rn
AND q.val = a.val
), blankcount AS
(
SELECT c = COUNT(*)
FROM AStringTab a
WHERE val = ''
), blankstring AS
(
SELECT
[s] = STUFF( (SELECT ',' + CAST(a.rn AS NVARCHAR(10))
FROM AStringTab a
WHERE a.val = ''
ORDER BY rn ASC
FOR XML PATH('')),
1, 1, '')
), matchingstring AS
(
SELECT
[s] = STUFF( (SELECT ',' + CAST(a.rn AS NVARCHAR(10))
FROM QStringTab q
JOIN AStringTab a
ON q.rn = a.rn
AND q.val = a.val
ORDER BY q.rn ASC
FOR XML PATH('')),
1, 1, '')
)
SELECT [statistics] = 'BlankString = ' + ISNULL(bs.s, '')
FROM blankstring bs
UNION ALL
SELECT [statistics] = 'BlankCount = ' + CAST(b.c AS NVARCHAR(100))
FROM blankcount b
UNION ALL
SELECT [statistics] = 'MatchingString = ' + ISNULL(ms.s, '')
FROM matchingstring ms
UNION ALL
SELECT [statistics] = 'Matchcount = ' + CAST(m.c AS NVARCHAR(100))
FROM matchcount m;
Doubts:
I assume that you want to compare values between commas and strings have the same number of commas
BlankCount should count from both or only #AString?
BlankString only for #AString, what if there are blank in both strings?
MatchingString should match blanks?
I removed last comma because it will be one more blank
This question already has answers here:
Concatenate row values T-SQL
(15 answers)
Closed 7 years ago.
I have the following table, sorted.
ID Value Amount
1 A 10.00
2 B 4.25
3 C 2.01
4 D 5.00
How can I concatenate only consecutive pairs of rows and turn it to this:
ID Col1 Col2
1,2 A,B 10.00,4.25
3,4 C,D 2.01,5.00
And I don't want to use user-defined tables or temp tables. I am open to using
the window functions provided in SQL Server 2012 and 2014 though.
I looked at the other solutions and thought it was overkill, so I reused some and excluded or rewrote the unnecessary parts. This should result in better performance.
;WITH cte (rn, id, Value, Amount)
AS
(
SELECT ROW_NUMBER() OVER(ORDER BY id), id, Value, Amount
FROM yourtable
)
SELECT
( SELECT CAST(T.id AS VARCHAR(10)) + ','+ CAST(T1.id AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn + 1) ID,
( SELECT CAST(T.value AS VARCHAR(10)) + ','+ CAST(T1.value AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn + 1) COL1,
( SELECT CAST(T.Amount AS VARCHAR(10)) + ','+ CAST(T1.Amount AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn + 1) COL2
FROM cte AS T
WHERE rn % 2 = 1
Try this,if it do not work with other sample data then let me know,
Declare #t table(ID varchar(50), Value varchar(50), Amount float)
insert into #t values(1,'A',10.00),(2,'B', 4.25),(3,'C',2.01)
,(4,'D',5.00 )
--Get the maxid
declare #MaxID int=(Select max(id) from #t)
;WITh CTE AS
(
SELECT ID,
STUFF((select ','+ id from #t where id IN(1,2) for xml path('')),1,1,'') [id1]
,STUFF((select ','+ Value from #t where id IN(1,2) for xml path('')),1,1,'') [Value]
,STUFF((select ','+ cast(Amount as varchar) from #t where id IN(1,2) for xml path('')),1,1,'') [Amount]
,1 RN
FROM #T a WHERE ID=1
UNION ALL
SELECT B.ID,
STUFF((select ','+ id from #t where id IN(RN+2,RN+3) for xml path('')),1,1,'')
,STUFF((select ','+ Value from #t where id IN(RN+2,RN+3) for xml path('')),1,1,'')
,STUFF((select ','+ cast(Amount as varchar) from #t where id IN(RN+2,RN+3) for xml path('')),1,1,'')
, RN+2
FROM cte a
CROSS APPLY(SELECT * FROM #T WHERE ID=RN+2 AND ID<=#MaxID) B
)
SELECT ID1,Value,Amount FROM CTE
This works just fine.. We just generate unique IDs for each pair using row_number and concatenate using FOR XML PATH on these IDs:
DECLARE #Test TABLE
(
ID VARCHAR(50)
, Value VARCHAR(50)
, Amount FLOAT
);
INSERT INTO #Test
(ID, Value, Amount)
VALUES
(1, 'A', 10.00)
, (2, 'B', 4.25)
, (3, 'C', 2.01)
, (4, 'D', 5.00);
;WITH cte (rn, id, Value, Amount)
AS
(
SELECT (ROW_NUMBER() OVER(ORDER BY id) + 1) / 2, id, Value, Amount
FROM #Test
)
SELECT DISTINCT
STUFF((SELECT ',' + CAST(T1.id AS VARCHAR(10))
FROM cte AS T1
WHERE T1.rn = T.rn
ORDER BY T1.id
FOR XML PATH('')), 1, 1, '') AS ID
, STUFF((SELECT ',' + CAST(T2.Value AS VARCHAR(10))
FROM cte AS T2
WHERE T2.rn = T.rn
ORDER BY T2.id
FOR XML PATH('')), 1, 1, '') AS Col1
, STUFF((SELECT ',' + CAST(T3.Amount AS VARCHAR(10))
FROM cte AS T3
WHERE T3.rn = T.rn
ORDER BY T3.id
FOR XML PATH('')), 1, 1, '') AS Col2
FROM cte AS T
Output:
ID Col1 Col2
-------------------
1,2 A,B 10,4.25
3,4 C,D 2.01,5
I have a table such as:
|Date |Name|
--------------------
|'20-May-2011'|Bob |
|'20-May-2011'|Fred|
|'20-May-2011'|Jim |
|'21-May-2011'|Bob |
|'21-May-2011'|Ed |
|'22-May-2011'|Bill|
I need a query to return:
|Date |Count|Names |
--------------------------------------
|'20-May-2011'| 3|'Bob, Fred, Jim'|
|'21-May-2011'| 2|'Bob, Ed' |
|'22-May-2011'| 1|'Bill' |
In other words, I want a list and a count of the names by date.
The best I can come up with is:
SELECT list.[Date], [Count], [Names]
FROM (
SELECT [Date],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
) [list]
INNER JOIN (
SELECT [Date],
COUNT(*) AS [Count]
FROM #table t
GROUP BY [Date]
) [count]
ON list.[Date] = count.[Date]
ORDER BY [Count] DESC, list.[Date]
Is there a more elegant query?
SELECT [Date],
COUNT(*) AS [Count],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
If you think that the Name column might contain <>'"& you should do like this instead:
SELECT [Date],
COUNT(*) AS [Count],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH(''), TYPE
).value('.', 'varchar(max)'), 1, 2, '') AS [Names]
FROM #table t
GROUP BY [Date]
Not a whole lot better - but maybe using a single CTE to "encapsulate" the XML-PATH-stuffing into a more presentable way would work??
;WITH ConsolidatedData AS
(
SELECT
[Date],
STUFF((
SELECT ', ' + [Name]
FROM #table t2
WHERE t2.[Date] = t.[Date]
ORDER BY [Name]
FOR XML PATH('')
), 1, 2, '') AS [Names]
FROM #table t
)
SELECT
[Date], Names, COUNT(*)
FROM
ConsolidatedData
GROUP BY
[Date], Names
Not sure if you'd count this as one "compound" statement, or two.... :-)
One word of advice: try not to use SQL Server identifiers and reserved words (like Date or Order) as your own column and/or table names.... it's always rather messy....