sql Id concatenation in sequence in a separate column like running total - sql

I need running Id concatenation just like running balance or total..
Concatenate the previous Ids to current Id row wise just like shown in picture
query is
with relation (Id, [orderSequence])
as
(
select Id,cast(Id as varchar(20))
from [ACChartofAccount]
union all
select p.Id, cast(Cast(r.Id as varchar) + ',' + cast(p.Id as varchar) as varchar(20))
from [ACChartofAccount] p
inner join relation r on p.ParentId = r.Id
)
select Id,orderSequence
from relation
order by orderSequence

You can use below query to get above result.
DECLARE #Table TABLE(ID VARCHAR(10));
INSERT INTO #table(ID) VALUES ('320'),(332),(333),(334),(335);
SELECT mt.ID,
STUFF((
SELECT ', ' + ID
FROM #table t
WHERE t.ID <= mt.ID
FOR XML PATH('')), 1, 2, '') AS oldersequence
FROM #table mt
ORDER BY ID

Related

Need distinct comma delimited product values order by date

I have below table structure
create TABLE PRODUCTDeatils
(
Product varchar(50),
Date Datetime
)
I want an output where i get comma separated list with distinct values but order by date.
I first split the values by below query
SELECT DISTINCT
LTRIM(RTRIM(value)) AS Product, date
INTO #tmp3
FROM PRODUCTDeatils
CROSS APPLY STRING_SPLIT(LTRIM(RTRIM(Product)), ',')
SELECT *
FROM #tmp3
ORDER BY date
Then I used below two queries to achieve it but not successful.
Query #1:
DECLARE #cols AS NVARCHAR(MAX);
SELECT #COLS = substring(list, 1, LEN(list) - 1)
FROM
(SELECT
list = (SELECT DISTINCT Product + ';'
FROM #tmp3
ORDER BY Product + ';'
FOR XML PATH(''), TYPE).value('.', 'nvarchar(MAX)')) AS T
SELECT #COLS
Query #2:
SELECT
STUFF((SELECT '; ' + Product
FROM
(SELECT DISTINCT TOP 100
Product,date
FROM #tmp3) x
ORDER BY date
FOR XML PATH('')), 1, 2, '') Text
I want output like above but bat should only come once.
In the more recent versions of SQL Server, you should just use string_agg():
SELECT STRING_AGG(Product, ',') WITHIN GROUP (ORDER BY date)
FROM (SELECT LTRIM(RTRIM(s.value)) AS Product, MIN(date) as date
FROM ProductDetails pd CROSS APPLY
STRING_SPLIT(LTRIM(RTRIM(pd.Product)), ',') s
GROUP BY LTRIM(RTRIM(s.value))
) p
Here is a db<>fiddle.
You can add row_number and select only one value per product.
SELECT DISTINCT
LTRIM(RTRIM(value)) AS Product, date, ROW_NUMBER() over (partition by trim(Value) order by date) rn
INTO #tmp3
FROM PRODUCTDeatils
CROSS APPLY STRING_SPLIT(LTRIM(RTRIM(Product)), ',')
SELECT
STUFF((SELECT '; ' + Product
FROM
(SELECT DISTINCT TOP 100
Product,date
FROM #tmp3 where rn = 1) x
ORDER BY date
FOR XML PATH('')), 1, 2, '') Text
Please find the db<>fiddle here.

create one row from two columns sql

How to create one row from two columns?
Example:
id description
------------------
1 one
2 two
3 three
In result:
1: one, 2: two, 3: three
I use follow statment:
select Id,
stuff((SELECT distinct ', ' + cast(Description as varchar(10))
FROM dbo.tbl t2
where t2.Id = t1.Id
FOR XML PATH('')),1,1,'')
from dbo.tbl t1
group by Id
But in result I have two columns. I need one such as string
You can try this query.
CREATE TABLE T (
id int,
description varchar(50)
);
INSERT INTO T VALUES (1,'one');
INSERT INTO T VALUES (2,'two');
INSERT INTO T VALUES (3,'three');
Query 1:
select
stuff((SELECT ', ' + CAST(t2.ID AS VARCHAR(5)) + ':'+ t2.description
FROM t t2
FOR XML PATH('')),1,1,'')
Results:
| |
|------------------------|
| 1:one, 2:two, 3:three |
i think you are asking for this
select stuff((SELECT ', ' + CAST(tbl.id AS varchar) + ':' + tbl.description
FROM tablename tbl FOR XML PATH('')), 1, 1, '') as Columnname
You were close..
declare #T TABLE (
id int,
description varchar(50)
);
INSERT INTO #T VALUES (1,'one');
INSERT INTO #T VALUES (2,'two');
INSERT INTO #T VALUES (3,'three');
select Id,
stuff((SELECT distinct ', ' + +cast(id as nvarchar) +':'+description
FROM #T t2
where t2.Id = t1.Id
FOR XML PATH('')),1,1,'')
from #T t1
group by Id
OR If you want all the ids in a sing row use the below query
select stuff((select ',' +cast(id as nvarchar) +':'+description
from #T for xml path('')),1,1,'')
select statement is like a for loop or an iterator and you you need a space to save you data and it's not possible with select only because in the moment select statement only access to a row not previous row and not next row so
please use a scaler-value function
create function test()
return
nvarchar(max)
as
begin
declare #s nvarchar(max)
select #s = concate(#s, id, description)
from yourTable
return #s
end

SQL Query using inner join

CategoryTable
Code Name
1 Food
2 Non-Food
Existing Table Consists list of category, as for example, I have two only Food and Non-Food
As challenge, I am assigning tenants with category or categories (multiple assignment, as there are tenants which are categorized as food and non-food). I i used to insert Tenant and Code to a new table creating this output
TenantAssignTable
Tenant Code
Tenant1 1,2
Tenant2 1
What I need to do, is to load the TenantAssingTable to gridview consisting the Name of the CategoryCode too like this
Desired Output
Tenant CCode Name
Tenant1 1,2 Food,Non-Food
Tenant2 1 Food
I used inner join in my code, but this is limited as I have a string of combined code in Code column.
Select a.tenant, a.ccode, b.name
from TenantAssignTable a inner join CategoryTable b
on a.CCode = b.code
Is there anyway to achieve this kind of output? I know that this is unusual in SQL coding but this is what is challenge as what the desired output is concerned and needs which is to have a multiple assignment of category to a single tenant.
Thanks in advance!
Think simple;
You can with LIKE and XML PATH
DECLARE #CategoryTable TABLE (Code VARCHAR(50), Name VARCHAR(50))
INSERT INTO #CategoryTable
VALUES
('1', 'Food'),
('2', 'Non-Food')
DECLARE #TenantAssignTable TABLE (Tenant VARCHAR(50), Code VARCHAR(50))
INSERT INTO #TenantAssignTable
VALUES
('Tenant1', '1,2'),
('Tenant2', '1')
SELECT
T.Tenant ,
T.Code,
STUFF(
(SELECT
',' + C.Name
FROM
#CategoryTable C
WHERE
',' + REPLACE(T.Code, ' ', '') + ',' LIKE '%,' + C.Code + ',%'
FOR XML PATH('')
), 1, 1, '') A
FROM
#TenantAssignTable T
Result:
Tenant Code A
--------------- ------------ ---------------
Tenant1 1,2 Food,Non-Food
Tenant2 1 Food
You can use some XML transformations:
DECLARE #x xml
SELECT #x = (
SELECT CAST('<t name="'+a.tenant +'"><a>'+REPLACE(a.code,',','</a><a>') +'</a></t>' as xml)
FROM TenantAssignTable a
FOR XML PATH('')
)
;WITH cte AS (
SELECT t.v.value('../#name','nvarchar(max)') as Tenant,
t.v.value('.','int') as CCode,
ct.Name
FROM #x.nodes('/t/a') as t(v)
INNER JOIN CategoryTable ct
ON ct.Code = t.v.value('.','int')
)
SELECT DISTINCT
c.Tenant,
STUFF((SELECT ','+CAST(CCode as nvarchar(10))
FROM cte
WHERE c.Tenant = Tenant
FOR XML PATH('')
),1,1,'') as CCode,
STUFF((SELECT ','+Name
FROM cte
WHERE c.Tenant = Tenant
FOR XML PATH('')
),1,1,'') as Name
FROM cte c
Output:
Tenant CCode Name
Tenant1 1,2 Food,Non-Food
Tenant2 1 Food
The first part (defining #x variable) will bring your table to this kind of XML:
<t name="Tenant1">
<a>1</a>
<a>2</a>
</t>
<t name="Tenant2">
<a>1</a>
</t>
Then in CTE part we join XML with table of categories. And after all get data from CTE with the help of FOR XML PATH.
Create Function as below which return Table from separated Value
CREATE FUNCTION [dbo].[fnSplit]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
Create Function as below which return comma separated Name
CREATE FUNCTION [dbo].[GetCommaSeperatedCategory]
(
#Codes VARCHAR(50)
)
RETURNS VARCHAR(5000)
AS
BEGIN
-- Declare the return variable here
DECLARE #Categories VARCHAR(5000)
SELECT #Categories= STUFF
(
(SELECT ',' + convert(varchar(10), Name, 120)
FROM Category
WHERE Code IN (SELECT Id FROM [dbo].[fnSplit] (#Codes,',') )
ORDER BY Code
FOR XML PATH (''))
, 1, 1, '')
RETURN #Categories
END
AND Last:
SELECT
Tenant,
Code,
(SELECT [dbo].[GetCommaSeperatedCategory] (Code)) AS Name
FROM TblTenant

How to make 2 rows into single row in sql

I have a query
example
Title Description
A XYZ
A ABC
now i want a sql query so that i can get a single row
Output :
Title Description
A XYZ | ABC
Declare #tbl table(Title nvarchar(1),[Description] nvarchar(100))
Insert into #tbl values('A','XYZ');
Insert into #tbl values('A','ABC');
Insert into #tbl values('A','PQR');
DECLARE #CSVList varchar(100)
SELECT #CSVList = COALESCE(#CSVList + ' | ', '') +
[Description]
FROM #tbl
WHERE Title='A'
SELECT #CSVList
declare #table table (i int, a varchar(10))
insert into #table
select 1, 'ABC' union all
select 1, 'XYZ' union all
select 2, '123'
select t.i,
max(stuff(d.i, 1, 1, '')) [iList]
from #table t
cross
apply ( select '|' + a
from #table [tt]
where t.i = tt.i
for xml path('')
) as d(i)
group
by t.i;
In mysql there is a group_concat function, that can help you.
Use it like this:
SELECT Title,GROUP_CONCAT(Description) FROM table_name GROUP BY Title
The output will be
Title Description
A XYZ,ABC
Then you can replace "," with "|" if you want(it can be done with replace function)
For 2 rows you can self join in SQL Server. This avoids the assorted "concatenate rows into a column" tricks. You can use a LEFT JOIN and NULL handling too for 1 or 2 rows
SELECT
T1.Title,
T1.Description + '|' + T2.Description
FROM
MyTable T1
JOIN
MyTable T2 ON T1.Title = T2.Title
SELECT
T1.Title,
T1.Description + ISNULL('|' + T2.Description, '') --COALESCE for the pedants)
FROM
MyTable T1
LEFT JOIN
MyTable T2 ON T1.Title = T2.Title
If you are using SQL Server, try this: How to return 1 single row data from 2 different tables with dynamic contents in sql

Duplicates without using While or Cursor in T-SQL

ID Name
1 A
1 B
1 C
2 X
2 Y
3 P
3 Q
3 R
These are the columns in a table. I want to get output like
ID Company
1 A,B,C
2 X, Y
3 P,Q,R
Restriction is that I cannot use WHILE or CURSOR. Please write a query for the same.
This query should do it - uses FOR XML PATH which is new in SQL Server 2005 - hope you are on 2005 or higher, you didn't clearly specify.....
SELECT
ID,
STUFF(CAST((SELECT ','+Name FROM dbo.YourTable t2
WHERE t2.ID = dbo.YourTable.ID
FOR XML PATH(''), TYPE) AS VARCHAR(MAX)), 1, 1, '') AS 'Company'
FROM
dbo.YourTable
GROUP BY
ID
Here's a solution using the CROSS APPLY method:
select id, sub.names
from (
select distinct id from YourTable
) a
cross apply (
select name + ', ' as [text()]
from YourTable b
where b.id = a.id
for xml path('')
) sub(names)
For 2005 version:
CREATE TABLE dbo.TEST([Type] INTEGER, [Name] NVARCHAR(100), [Qty] INTEGER)
GO
INSERT dbo.TEST VALUES(1, N'a', 5)
INSERT dbo.TEST VALUES(1, N'b', 6)
INSERT dbo.TEST VALUES(2, N'c', 44)
INSERT dbo.TEST VALUES(3, N'd', 1)
GO
select [Type],
[Description] = replace((select [Name] + ':' + cast([Qty] as varchar) as 'data()'
from TEST where [Type] = t.[Type] for xml path('')), ' ', ',')
from dbo.TEST t
group by [Type]
go
drop table dbo.TEST
You can group on the ID to get the unique values, then get the comma separated string for each using a for xml query:
select
a.ID,
substring((
select ', ' + Name
from Test1
where Test1.ID = a.ID
for xml path('')
), 3, 1000) as Company
from
TheTable a
group by
a.ID