Correlation items like amazon.com - sql-server

we are in retail company and they need correlation items that have related together
in sales may sales id have full combination or have more than them
1. a b 1200
2. a c 1700
3. a b c 1200
i was tring
select [itemids],count(*)from (
SELECT
S.Salesid ,
STUFF((SELECT ', ' + S1.itemid
FROM banta_sales_ts S1
WHERE S.Salesid = S1.Salesid
FOR XML PATH('')), 1, 1, '') [itemids]
FROM banta_sales_ts S
GROUP BY S.Salesid) as grp group by [itemids]
but that related salesid i need full correlation items

Related

Merge multiple rows into a column while replacing the keys with a 'name' field from the original table

I've got a join table that has 'account_id' and 'group id' in it, both represented by a GUID. I'm trying to merge the columns so we get a single 'account_id' with all of it's 'group_id's merged to a single Colum/row, but display the actual name of the account and group.
Tables
Account
account_id Name
1 Henry
2 Smith
Group
Group_id Group_nameName
3 User
4 Admin
Account_Group_Join_Table
account_id group_id
1 3
1 4
2 3
Desired Result:
Name Groups
Henry Dev,User
Smith User, Admin
Code so far to return 'account_id' with 'group_id' grouped to single row/column
select account_id,
stuff((SELECT distinct ', ' + group_id
FROM account_group_join t2
where t2.account_id = t1.account_id
FOR XML PATH('')),1,1,'') [Groups]
from account_group_join t1
group by account_id
You just need to join to your group table in the subquery so you can get the name rather than the ID. You also may as well just select from Account in the outer query and avoid an additional join to account to get the name:
SELECT a.account_id,
a.Name,
STUFF((SELECT DISTINCT ', ' + g.group_nameName
FROM account_group_join AS ag
INNER JOIN [Group] AS g
ON g.group_id = ag.group_id
WHERE ag.account_id = a.account_id
FOR XML PATH('')),1,1,'') AS [Groups]
from Account AS a;
n.b. I've changed your aliases from t1 and t2 to something that kind of represents the table I am aliasing, you'll find this much easier especially when working with larger queries. More reading here: Bad Habits to Kick : Using table aliases like (a, b, c) or (t1, t2, t3)

Substitute for STRING_AGG pre SQL Server 2016

I need to group a table by a set of values together with all matching row numbers/id:s for each set. This operation must be done within the boundaries of SQL Server 2016.
Let's suppose I have the following table (Places):
ID
Country
City
1
Sweden
Stockholm
2
Norway
Oslo
3
Iceland
Reykjavik
4
Sweden
Stockholm
The result that I'm after (No curly-brackets because Stack Overflow thinks it's code, preventing me from posting):
ID
Json
1,4
"Country":"Sweden","City":"Stockholm"
2
"Country":"Norway ","City":"Oslo"
3
"Country":"Iceland ","City":"Reykjavik"
In SQL Server 2017 the above result can be achieved with:
SELECT STRING_AGG(ID) ID, (SELECT Country, City FOR JSON PATH) Json
FROM Places GROUP BY Country, City
I managed to get a similar result in SQL Server 2016 with the code below. (But with my actual amount of data and columns, this solution is too slow.)
SELECT DISTINCT Country, City INTO #temp FROM Places
SELECT (SELECT ID From Places WHERE Country = P.Country AND City = P.City FOR JSON PATH) ID,
(SELECT Country, City FOR JSON Path) Json FROM #temp P
Is there any more performance-effective way of achieving the result that I'm after?
EDIT: As people suggested me to try "FOR XML Path" I tried the code below. This gives the following error "Places.ID is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause ":
SELECT stuff((select ',' + cast(ID as varchar(max)) for xml path ('')), 1, 1, '') ID,
(SELECT Country, City FOR JSON PATH) Json
FROM Places GROUP BY Country, City
Here's a solution you can try with for xml path
Basically select and group the json columns needed and using an apply, use the for xml path solution to aggregate the correlated ID values; because the outer query needs to refer to the output of the apply it needs to be aggregated also, I chose to use max
select max(x.Ids), (select country,city for json path) as [Json]
from t
outer apply (
select Stuff((select ',' + Convert(varchar(10),t2.Id)
from t t2
where t2.city=t.city and t2.country=t.country
for xml path(''),type).value('(./text())[1]','varchar(10)'),1,1,'') as Ids
)x
group by country,city
Working Fiddle
Here is another possible solution:
Declare #testTable Table (ID int, Country varchar(30), City varchar(30));
Insert Into #testTable (ID, Country, City)
Values (1, 'Sweden', 'Stockholm')
, (2, 'Normway', 'Oslo')
, (3, 'Iceland', 'Reykjavik')
, (4, 'Sweden', 'Stockholm');
Select Distinct
ID = stuff((Select concat(',', tt2.ID)
From #testTable tt2
Where tt2.City = tt.City
And tt2.Country = tt.Country
For xml path (''), Type).value('.', 'varchar(10)'), 1, 1, '')
, json = (Select Country, City For JSON PATH)
From #testTable tt;
No idea if this will perform any better though. It is essentially the same - just using DISTINCT instead of GROUP BY.

Combine Multiple Rows into one row on a single table

I have a table that contains multiple Insurance policies for each client that contains
Order (Primary, Secondary etc. up to 9 possible Insurance policies)
I need one row per client containing all the client's insurance policies in order of importance.
for example:
Client, Order, Company, Number, Start, End, Co-Pay, Active?
1 1 BCBS 12345 1/1/2019 $10 Active
1 2 Medicare X21Y52 2/1/2018 Active
1 6 Self-Pay
2 6 Medicare X21Y52 2/1/2018 Active
2 8 Self-Pay
I need a single row for each Client with the data for each Active Policy
1,1,BCBS,12345,1/1/2019,,$10,Active,2,Medicare,X21Y52,2/1/2018,,,Active,6,Self-Pay,,,,,
2,6,Medicare,x22y22,7/1/2002,,,Active,8,Self-Pay,,,,,,
How can I code to get the desired result.
There is a maximum of 9 policy references
Only want Active policies
As you didn't post your schema, i just make some assumption on the data type. Note that you need to convert to string before concatenation
select t.Client, stuff(csv, 1, 1, '')
from (
select distinct Client
from a_table t
) t
cross apply
(
select ',' + coalesce(x.Company, '') +
',' + coalesce(x.Number, '') +
',' + coalesce(convert(varchar(10), [Start], 121), '') +
',' + . . .
from a_table x
where x.Client = t.Client
and x.Active = 'Active'
order by [Order]
for xml path ('')
) c (csv)

Unable to use XML PATH with UNION ALL in SQL Server

I have used below code to generate Comma separate values, it was before perfect working without UNION ALL but once I apply UNION ALL with another SELECT then it is showing an XML like output. The query looks like:
SELECT ISNULL(STUFF((
SELECT plant from (
SELECT DISTINCT ', ' + Plant as Plant
FROM ASP_MstSKUPlantMapping SKUPM
WHERE SKUID = '702953' AND Plant LIKE 'P%'
UNION ALL
SELECT DISTINCT ', ' + Plant as Plant
FROM ASP_MstSKUPlantMapping SKUPM
WHERE SKUID = '702953' AND Plant LIKE 'S%'
) Temp
FOR XML PATH('')), 1, 2,''),'')
Current Output:
lant>, PN05</plant><plant>, PN10</plant>
Expected Output:
PN05, PN10
EDIT: If I removed as Plant this alias name then it showing an error as:
No column name was specified for column 1 of 'Temp'.
I don't think you need to use a UNION ALL for this.
It's from the same table, so it's just something for the WHERE clause to deal with.
SELECT
ISNULL(STUFF((
SELECT CONCAT(', ', Plant)
FROM ASP_MstSKUPlantMapping SKUPM
WHERE SKUID = '702953' AND Plant LIKE '[PS]%'
GROUP BY Plant
ORDER BY Plant
FOR XML PATH('')
), 1, 2, ''),'') AS [Plants];

Sql Multiple row merge into single row with specific pattern

Sql select query which gives merge multiple row into one single row
using sqlserver 2005 and above
I have two tables ie (tb_master,tb_tasks)
create table tb_tasks(
id int IDENTITY(1,1) NOT NULL,
id_tbmaster int NOT NULL,
Tasks nvarchar(max) NOT NULL
)
create table tb_master(
id int IDENTITY(1,1) NOT NULL,
grade nchar(10) NOT NULL,
name nvarchar(50) NOT NULL,
task_date datetime NOT NULL,
)
select * from tb_master
id grade name task_date
1 A John 2012-02-13 10:40:00.000
2 B Tom 2012-02-13 10:40:00.000
select tb_tasks
id id_tbmaster Tasks
1 1 cooking food.
2 1 Programing 2 hours
3 1 Attending meeting
4 2 Driving car
5 2 hangout with friends
Have tried this query
select tasks + ' , ' as 'data()' from tb_tasks for xml path('')
Gives Output
XML
cooking food , Programing 2 hours , Attending meeting , Driving car , hangout with friends ,
I need output like
id Name grade task_date tasksDetails
1 John A 2012-02-13 10:40:00.000 1)cooking food, 2)Programing 2 hours, 3)Attending meeting
2 Tom B 2012-02-13 10:40:00.000 1) Driving car, 2)hangout with friends
Query i tried
select a.name,a.task_date,b.tasks =replace(select (CONVERT(VARCHAR,(ROW_NUMBER() OVER(ORDER BY id DESC)))) + ') ' + tasks + ' , ' as 'data()'
from tb_tasks for xml path(''))
from tb_master a inner join tb_tasks b
on a.id=b.id_tbmaster
Thanks in advance
This query will create requested list of activities per tb_master. Two pointers: one should match ordering in row_number() over() and in query to get consistent results, and number 3 in last row of OUTER APPLY is number of characters in separator (in this case, ' , '). If you change separator you need to adjust this number.
select a.name,a.task_date, b.taskList
from tb_master a
OUTER APPLY
(
select stuff ((select ' , '
+ CONVERT(VARCHAR(10), ROW_NUMBER()
OVER(ORDER BY id DESC))
+ ') '
+ tasks
from tb_tasks b
where a.id = b.id_tbmaster
order by id desc
for xml path (''))
, 1, 3, '') taskList
) b
Live demo is at Sql Fiddle.

Resources