Home > database >  How to use Group By with where condition to concatenate column value in SQL Server
How to use Group By with where condition to concatenate column value in SQL Server

Time:11-01

I want to return asset count as per type and also want to concatenate asset ids. I am using FOR XML and path which works fairly good but as soon as I add where clause, it does not work as expected.

This is my table schema and query:

CREATE TABLE [dbo].[Asset]
(
    [AssetSeqNumber] [bigint] NULL,
    [AssetType] [varchar](100) NULL
) ON [PRIMARY]
GO

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (1, N'Tree')

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (2, N'Tree')

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (3, N'Tree')

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (4, N'Barbecue')

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (5, N'Bridge')

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (101, N'Tree')

INSERT [dbo].[Asset] ([AssetSeqNumber], [AssetType]) 
VALUES (102, N'Tree')
GO

Query:

SELECT
    AssetType, 
    COUNT(AssetSeqNumber) AS count,
    STUFF((SELECT DISTINCT ','   CAST(AssetSeqNumber AS varchar(100))
           FROM Asset
           WHERE AssetType = a.AssetType 
           FOR XML PATH ('')), 1, 1, '') AS AssetIds
FROM 
    Asset AS a
WHERE
    a.AssetSeqNumber IN (1, 2, 3, 4, 5)
GROUP BY 
    AssetType

enter image description here

This query return result for ids which are not in the where condition (i.e. 101,102). I understand it is because inner query check asset types but I can't figure out how to show expected result.

Note: I am using SQL Server 2019 (v15.0.2095.3 (X64))

CodePudding user response:

You need to modify the where clause for the select statement inside the STUFF function as the following:

WHERE AssetType = a.AssetType AND AssetSeqNumber IN (1, 2, 3, 4, 5)

Also, for your version of SQL Server, you could simplify this by using STRING_AGG function as the following:

SELECT AssetType, 
       COUNT(*) [Count],
       STRING_AGG(AssetSeqNumber, ',') AssetIds
FROM Asset
WHERE AssetSeqNumber IN (1, 2, 3, 4, 5)
GROUP BY AssetType 

See a demo for both queries.

CodePudding user response:

your data

drop table if exists #Asset
CREATE TABLE #Asset
(
    [AssetSeqNumber] [bigint] NULL,
    [AssetType] [varchar](100) NULL
) ON [PRIMARY]
GO

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (1, N'Tree')

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (2, N'Tree')

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (3, N'Tree')

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (4, N'Barbecue')

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (5, N'Bridge')

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (101, N'Tree')

INSERT #Asset ([AssetSeqNumber], [AssetType]) 
VALUES (102, N'Tree')
GO

you should add your condition into your Xml query

 SELECT
    AssetType, 
    COUNT(AssetSeqNumber) AS count,
    STUFF((SELECT DISTINCT ','   CAST(AssetSeqNumber AS varchar(100))
           FROM #Asset
           WHERE AssetType = a.AssetType /*yourcondition*/and AssetSeqNumber IN (1, 2, 3, 4, 5)
           FOR XML PATH ('')), 1, 1, '') AS AssetIds
FROM 
    #Asset AS a
WHERE
    a.AssetSeqNumber IN (1, 2, 3, 4, 5)
GROUP BY 
    AssetType

by consider using SQL Server 2019,you can use string_agg

SELECT [assettype],
       Count(assetseqnumber)           count,
       String_agg(assetseqnumber, ',') AssetIds
FROM   #asset a
WHERE  a.assetseqnumber IN ( 1, 2, 3, 4, 5 )
GROUP  BY [assettype]  
  • Related