SQL Concatenation using XML Path - multiple rows with multiple table references - sql

I am trying to use the XML Path to run SQL Concatenation but I am running into a bit of a problem. I have one table that is being used as a reference table for values I want to concatenate.I have 3 columns in the reference table (M.PROD, S.PROD, & REF NUMB).
M.PROD=====>S.PROD======>Ref Numb
1===========>_===========>981024583
2===========>_===========>981024719
3===========>A===========>981024605
3===========>B===========>981024669
4===========>A===========>981024688
4===========>B===========>981024706
4===========>C===========>981024723
5===========>_===========>981024742
6===========>_===========>981024742
I have the main tables where the m.prod and s.prod are used to match the reference table for Ref Numb values. What I want to do is concatenate the Ref Numb values based on what is being selected in main tables. The out put I am looking for is this:
M.Prod======>Ref Numb
1===========>981024583
2===========>981024719
3===========>981024605, 981024669
4===========>981024688, 981024706, 981024723
5===========>981024742
6===========>981024742
I am using the following query:
SELECT DISTINCT P.PRODUCT,
(STUFF((SELECT DISTINCT ',' + P1.REFNUMB AS [text()]
FROM PRODUCT P1
WHERE P1.PRODUCT = P.PRODUCT
FOR XML PATH('')), 1, 1, ''))
FROM PRODUCT P
This gives me the output of:
M.Prod======>Ref Numb
1===========>981024583
2===========>981024719
3===========>981024605, 981024669
4===========>981024688, 981024706, 981024723
5===========>981024742
6===========>981024742
However, there are times where all the s.prod are not in the main tables. So for this I use this query:
SELECT DISTINCT P.PRODUCT,
(STUFF((SELECT DISTINCT ',' + P1.REFNUMB AS [text()]
FROM PRODUCT P1
WHERE P1.PRODUCT = P.PRODUCT AND P1.SUBID = P.SUBID
FOR XML PATH('')), 1, 1, ''))
FROM PRODUCT P
This query produces following output for me:
M.Prod======>Ref Numb
1===========>NULL
2===========>NULL
3===========>981024605
3===========>981024669
4===========>981024688
4===========>981024723
5===========>NULL
6===========>NULL
The output I need in these cases is:
M.Prod======>Ref Numb
1===========>981024583
2===========>981024719
3===========>981024605, 981024669
4===========>981024688, 981024723
5===========>981024742
6===========>981024742
Any solution for this will be greatly appreciated, Thank you.

I'm not sure if I understood your question correctly, but try this:
SELECT DISTINCT P.PRODUCT,
(STUFF((SELECT DISTINCT ',' + P1.REFNUMB AS [text()]
FROM PRODUCT P1
WHERE P1.PRODUCT = P.PRODUCT
AND (P1.SUBID = P.SUBID OR P1.SUBID IS NULL AND P.SUBID IS NULL)
FOR XML PATH('')), 1, 1, ''))
FROM PRODUCT P

Related

Merging multiple rows of data into same column

I would like to create a table of job ids and a column listing all the different job categories that get matched up, but concatenated into the same column. As an example, right now job 82041 has two categories, but now is returning two rows. I would like for it to say "Retail, Sales Associate", all in one field.
The code that I tried is below, can anybody tell me what I am doing wrong?
EXAMPLE:
jobOrderID (No column name)
82027 Motion Graphics
82029 Other
82030 Product Designer
82041 Retail
82041 Sales Associate
82069 Social Media
EXAMPLE CODE:
select JobOrder.jobOrderID ,
stuff((select distinct ', ' + cast(Category.occupation as nchar(30))
from Category
where Category.categoryID = JobOrderCategories.categoryID
for xml path ('')),1,1,'')
from JobOrder
left outer join JobOrderCategories
on JobOrder.joborderid = JobOrderCategories.jobOrderID
left outer join Category
on Category.categoryID = JobOrderCategories.categoryID
where JobOrder.dateAdded > '2017-5-2' and JobOrder.dateAdded < '2017-5-3'
and joborder.isDeleted = 0
order by joborder.dateAdded asc
Figured it out by altering the left joins
select
JobOrder.jobOrderID,
stuff((select distinct ', ' + cast(Category.occupation as varchar(30))
from Category
left outer join JobOrderCategories on (Category.categoryID = JobOrderCategories.categoryID and joborder.jobOrderID = JobOrderCategories.joborderid)
where Category.categoryID = JobOrderCategories.categoryID
for xml path ('')),1,1,'')
from JobOrder
where JobOrder.dateAdded > '2017-5-2' and JobOrder.dateAdded < '2017-5-3'
and joborder.isDeleted = 0

SQL server Stuff on multiple columns

I want to concatenate the value of multiple columns for the same ID.
I managed to concatenate for the first column, but when trying the same syntax for the second I'm having an error "The multi-part identifier EnqAct.[ActionID] could not be bound."
Example_Data_Result
Here I managed to group several MachineName together, as seen in "Column1" but I can't manage to group both the MachineName and Description in their own column
My working Query :
SELECT Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
Stuff((SELECT ', ' + Mach.[MachineName]
FROM [dbo].[Machine] Mach
INNER JOIN [dbo].[MachineEnquiry] MachEnq
ON Mach.[MachineID] = MachEnq.[MachineID]
WHERE Enq.[EnquiryID] = MachEnq.[EnquiryID]
FOR XML PATH('')), 1, 2, ''),
DetAct.[Description]
FROM [dbo].[Enquiry] Enq
INNER JOIN [dbo].[EnquiryAction] EnqAct
ON EnqAct.[EnquiryID] = Enq.[EnquiryID]
INNER JOIN [dbo].[DetailsAction] DetAct
ON DetAct.[ActionID] = EnqAct.[ActionID]
INNER JOIN [dbo].[DetailsPriority] DetPrio
ON DetPrio.[PriorityID] = Enq.[Priority]
GROUP BY Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
DetAct.[Description]
My non working Query :
SELECT Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
Stuff((SELECT ', ' + Mach.[MachineName]
FROM [dbo].[Machine] Mach
INNER JOIN [dbo].[MachineEnquiry] MachEnq
ON Mach.[MachineID] = MachEnq.[MachineID]
WHERE Enq.[EnquiryID] = MachEnq.[EnquiryID]
FOR XML PATH('')), 1, 2, ''),
Stuff((SELECT ', ' + DetAct.[Description]
FROM [dbo].[DetailsAction] DetAct
INNER JOIN [dbo].[EnquiryAction] EnqAct
ON EnqAct.[ActionID] = DetAtc.[ActionID]
WHERE Enq.[EnquiryID] = EnqAct.[EnquiryID]
FOR XML PATH('')), 1, 2, '')
FROM [dbo].[Enquiry] Enq
INNER JOIN [dbo].[DetailsPriority] DetPrio
ON DetPrio.[PriorityID] = Enq.[Priority]
GROUP BY Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description]
Both work the same way, I have a table Enquiry which will have an EnquiryID.
then in my table EnquiryAction or MachineEnquiry I will have entitys with an EnquiryID and an Action/Machine ID
Then in my DetailsAction/Machine Table I will have the Action/Machine ID, and the string I want to get and concatenate.
Why am I having an error and is it possible to achieve what I'm trying to do ?

What Is Wrong With This FOR XML PATH

I can't seem to figure out why this won't work in MS SQL Server. It seems to not group the lines. Specifically I see:
1036 SC
1036 S1
1094 VO
1094 V1
1094 V2
When I expect to see:
1036 SC,S1
1094 VO,V1,V2
Can someone see something wrong with the syntax?
SELECT DISTINCT oa.acct_cd AS [Account],
STUFF((SELECT ',' + CASE WHEN o.trans_type like 'BUY%' then 'buy of ' else 'sell of ' end + s.ticker AS [text()]
FROM [dbo].[synCRtblTS_ORDER] o INNER JOIN [dbo].[synCRtblCSM_SECURITY] s
ON o.SEC_ID = s.SEC_ID
WHERE o.ORDER_ID = oa.ORDER_ID AND o.status IN ('OPEN','WORK','PENDING')
FOR XML PATH('')), 1, 1, '') [buy/sell]
FROM [dbo].[synCRtblTS_ORDER_ALLOC] oa INNER JOIN tblPortfolio p
ON oa.ACCT_CD = p.Account INNER JOIN tblInvestmentObjective io
ON io.Code = p.InvestmentObjective
WHERE p.AsOfDate = (SELECT AsOfDate FROM tblDateAsOf) and io.CashMgmtStrategy IN ('SC','VO')
GROUP BY oa.ORDER_ID, oa.acct_cd
order by 1
The Information you give is not enough... Within your STUFF you create (and concatenate) string which should contain "buy of" or "sell of". You are missing this information in your output.
It's guessing that your SC, S1, VO values are CashMgmtStrategy entries. You are not concatenating them...
Without deeper knowledge of your tables I cannot solve your problem, but here you'll find a working example of concatenation via FOR XML and STUFF
This code will list all table's names and their columns in a comma delimited list.
SELECT DISTINCT tbls.name AS TableName,
STUFF(
(
SELECT ', ' + cols.name
FROM sys.columns AS cols
WHERE cols.object_id = tbls.object_id
FOR XML PATH('')
), 1, 2, '') AS ColumnList
FROM sys.tables AS tbls

SQL Pivot on Foreign Key but display different column header

I had written a stored procedure that would first get a list of columns which were distinct account descriptions and use those to pivot on for getting daily monetary values per account. The problem I encountered is the end user has instances where they have the same Account description for multiple accounts so I am now using AccountID's to pivot on.
Below you will find my query to get Distinct Account ID's and then to create the pivot table. My end goal is that the current column headers for the user are useless i.e. "1504" "1505" "1683" etc. These have no meaning to them. How can I either rename column headers of a result set or somehow use a pivot based on distinct account ID's while displaying a description instead. GLAccounts.Description is the column with the description I would like to display instead of the GLAccounts.AccountID.
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(AccountID)
FROM (
SELECT DISTINCT GLAccounts.AccountID AS AccountID
FROM GeneralLedger
INNER JOIN DailyFiles ON GeneralLedger.DailyFileID = DailyFiles.DailyFileID
Inner Join GLAccounts ON GeneralLedger.AccountID = GLAccounts.AccountID
-- Get All Daily Files for company and date range
INNER JOIN
(SELECT DailyFileID
FROM DailyFiles
WHERE (DailyFiles.DailyFileDate >= CONVERT(DATETIME, #MTDStart, 102)) AND (DailyFiles.DailyFileDate <= CONVERT(DATETIME, #MTDEnd, 102))
AND CompanyID = #CompanyID) AS DAILYFILEIDS ON GeneralLedger.DailyFileID = DAILYFILEIDS.DailyFileID
) x
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = N'SELECT A.*
from(
SELECT SummedAccounts.Date, SUM(SummedAccounts.DayTotal) AS DayTotal, SummedAccounts.AccountID AS AccountID
FROM(SELECT DailyFiles.DailyFileDate AS Date, IIF(GLAccounts.FriendlyName IS NOT NULL AND GLAccounts.FriendlyName <> '''', GLAccounts.FriendlyName, GLAccounts.Description) as AccountDescription, IIF(GeneralLedger.SavedToCredit = 1,
--Saved To Credit Is True
IIF(AccountTYpes.PositiveToCredit = 1, (SUM(GeneralLedger.Credit + GeneralLedger.Debit)), (SUM(GeneralLedger.Credit + GeneralLedger.Debit) * -1)),
--Saved To Credit Is False
IIF(AccountTYpes.PositiveToCredit = 1, ( SUM(GeneralLedger.Credit + GeneralLedger.Debit) * -1), (SUM(GeneralLedger.Credit + GeneralLedger.Debit)))) AS DayTotal, GeneralLedger.SavedToCredit, AccountTypes.PositiveToCredit, GeneralLedger.AccountID AS AccountID
FROM GeneralLedger
INNER JOIN DailyFiles ON GeneralLedger.DailyFileID = DailyFiles.DailyFileID
Inner Join GLAccounts ON GeneralLedger.AccountID = GLAccounts.AccountID
INNER JOIN AccountTypes ON AccountTypes.AccountTypeID = GLAccounts.AccountTypeID
-- Get All Daily Files for company and date range
INNER JOIN
(SELECT DailyFileID
FROM DailyFiles
WHERE (DailyFiles.DailyFileDate >= #MTDStart) AND (DailyFiles.DailyFileDate <= #MTDEnd)
AND CompanyID = #CompanyID) AS DAILYFILEIDS ON GeneralLedger.DailyFileID = DAILYFILEIDS.DailyFileID
GROUP BY GeneralLedger.AccountID, DailyFiles.DailyFileDate, GLAccounts.FriendlyName, GLAccounts.Description, GeneralLedger.SavedToCredit, AccountTypes.PositiveToCredit) SummedAccounts
GROUP BY SummedAccounts.Date, SummedAccounts.AccountID
) y
pivot
(
min(DayTotal)
for AccountID in (' + #cols + ')
) A'
Result Sets Look Like:

How to make a query with group_concat in sql server/powerpivot

I need help on my query. I am trying to concatenate DonorIntent so that each BudgetNbr has a one to one relationship with the DonorIntnet field. Currently I am exlcuding the BudgetNbrs with multiple DonorIntent (820655 and 820885)
The below hasn't worked for me so any help would be great!
SELECT
vwGEGiftEndowmentSummary.BudgetNbr
,vwGEGiftEndowmentSummary.BudgetName
,ODSBudgetIndexCurrent.OrgCode
,ODSBudgetIndexCurrent.BudgetStatus
,DonorIntent = STUFF((
SELECT ',' + vwGEGiftEndowmentSummary.DonorIntent
FROM vwGEGiftEndowmentSummary di
WHERE di.BudgetNbr = vwGEGiftEndowmentSummary.BudgetNbr
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM
vwGEGiftEndowmentSummary
INNER JOIN SOMOrgDeptGroups
ON vwGEGiftEndowmentSummary.Org_dept = SOMOrgDeptGroups.OrgDeptLevel
INNER JOIN ODSBudgetIndexCurrent
ON vwGEGiftEndowmentSummary.BudgetNbr = ODSBudgetIndexCurrent.BudgetNbr
WHERE
SOMOrgDeptGroups.ExtFundExpGroup = N'ADMIN'
AND ODSBudgetIndexCurrent.BudgetType IN (N'06', N'54')
AND vwGEGiftEndowmentSummary.BudgetNbr NOT IN (N'820655', N'820885')
GROUP BY
vwGEGiftEndowmentSummary.BudgetNbr
,vwGEGiftEndowmentSummary.BudgetName
,DonorIntent
,ODSBudgetIndexCurrent.OrgCode
,ODSBudgetIndexCurrent.BudgetStatus
Question resolved. I needed to remove GROUP BY DonorIntent and place into the subquery