I need to filter the results from my STUFF function which are held in the column 'combined_ops'. I need to only see records that do not contain the word 'Transfer'. I've tried the classic WHERE combined_ops NOT LIKE '%transfer%', but does not work. See my code and results and please let me know where I went wrong. Thank You.
SELECT Job, STUFF((SELECT DISTINCT ' ' + Operation_Service
FROM dbo.Job_Operation
WHERE dbo.Job_Operation.Job = dbo.Job.Job
for xml path('')),1,2,'') AS combined_ops
FROM dbo.Job
WHERE dbo.Job.Status = 'Active'
AND dbo.Job.Customer_PO = 'tmi stock'
enter image description here
There are a few ways to do this.
You can put the FOR XML in a CROSS APPLY and filter afterwards
SELECT
j.Job,
jo.combined_ops
FROM dbo.Job j
CROSS APPLY (SELECT
STUFF((SELECT DISTINCT ' ' + jo.Operation_Service
FROM dbo.Job_Operation jo
WHERE jo.Job = j.Job
for xml path(''), type
).value('text()[1]','nvarchar(max)'),1,2,'')
) AS jo(combined_ops)
WHERE j.Status = 'Active'
AND j.Customer_PO = 'tmi stock'
AND jo.combined_ops NOT LIKE '%transfer%'
Or you can use HAVING and conditional aggregation
SELECT Job,
STUFF((
SELECT ' ' + jo.Operation_Service
(
SELECT jo.Operation_Service
FROM dbo.Job_Operation jo
WHERE jo.Job = j.Job
GROUP BY jo.Operation_Service
HAVING COUNT(CASE WHEN jo.Operation_Service LIKE '%transfer%' THEN 1 END) = 0
) jo
for xml path(''), type
).value('text()[1]','nvarchar(max)'),1,2,'') AS combined_ops
FROM dbo.Job j
WHERE j.Status = 'Active'
AND j.Customer_PO = 'tmi stock'
Note the use of the syntax for xml path(''), type).value('text()[1]','nvarchar(max)') to unescape XML characters correctly.
Note also the use of table aliases rather than three part column names.
Related
I have applied XML PATH and Stuff to show multiple records in single cell, which is all working fine but I am required to show each record in cell in separate single line i.e char(13) but in my solution I am getting result like
#x0D;; Canvey
; government
; More information needed
; More information required
Script
SELECT
ans.Id
,ans.ResponseId
,STUFF((SELECT DISTINCT
char(13)+char(10) +
'; ' + cod.Name
,' ' + COUNT(cod.Name)
FROM [dbo].[Highlights] as h
INNER JOIN [dbo].[CodedHighlights] as ch on h.Id = ch.HighlightId
INNER JOIN [dbo].[Codes] as cod on ch.CodeId = cod.Id
WHERE h.AnswerId = ans.Id
GROUP BY cod.Name
FOR XML PATH('')), 1, 1, '' ) [ANSWER/CODES]
FROM [dbo].[Answers] as ans
Try this
DECLARE #result VARCHAR(100)=
STUFF(
(
SELECT TOP 5 CHAR(13) + [name]
FROM sys.objects
FOR XML PATH(''),TYPE).value('.','nvarchar(max)'),1,1,'');
PRINT #result;
You must use TYPE to get a natively typed XML in order to use the .value() method. This will implicitly re-escape all entities to their actual string values.
Furthermore, I use PRINT, as the typical grid result would not show the line breaks.
Hint: If you use CHAR(13)+CHAR(10) you'd have to add ,1,2,'') as STUFF()'s paramaters.
I am trying to get all route path separating with arrow (-->). But the arrow (-->) does not work, it is shown as -->.
SELECT
vrmd.LocationName + '--> '
FROM
dbo.tbl_VehicleRouteMapDetail vrmd
WHERE
vrmd.VrmapId = 1
ORDER BY
vrmd.VrmapId
FOR XML PATH('')
But it's working perfectly this way:
DECLARE #Route VARCHAR(MAX)= ''
SELECT #Route = #Route + vrmd.LocationName + '--> '
FROM dbo.tbl_VehicleRouteMapMaster vrmm
INNER JOIN dbo.tbl_VehicleRouteMapDetail vrmd ON vrmd.VrmapId = vrmm.VrmapId
ORDER BY vrmd.VrmapDetailId ASC
Why choose first query?
I need to use this query as subquery. In this case second query does not work for me:
SELECT
COUNT(ewva.VehicleId) Allocation, vii.Capacity,
STUFF((SELECT vrmd.LocationName + '=> '
FROM dbo.tbl_VehicleRouteMapDetail vrmd
WHERE vrmd.VrmapId = vrmm.VrmapId
ORDER BY vrmd.VrmapId
FOR XML PATH('')), 1, 1, '') AS name_csv
FROM
dbo.tbl_VehicleInfoInternal vii
INNER JOIN
dbo.tbl_EmpWiseVehicleAllocation ewva ON ewva.VehicleId = vii.VehicleId
INNER JOIN
dbo.tbl_VehicleRouteMapMaster vrmm ON vrmm.VehicleId = vii.VehicleId
GROUP BY
ewva.VehicleId, vii.Capacity, vrmm.VrmapId
Any help would be appreciated.
It's as simple as adding the TYPE directive to your FOR XML clause (docs here). This will return the result as an instance of the XML type rather than text. Text will have certain characters (e.g. > and <) translated (> and <) to fit within an XML element.
SELECT
vrmd.LocationName + '--> '
FROM
dbo.tbl_VehicleRouteMapDetail vrmd
WHERE
vrmd.VrmapId = 1
ORDER BY
vrmd.VrmapId
FOR XML
PATH(''), TYPE
I am attempting the following query in SQL Server:
SELECT AlertID,
(STUFF((SELECT ', ' + t2.LocationDesc
FROM app_Location t2
WHERE t1.LocationCode = t2.LocationCode
FOR XML PATH (''))
, 1, 1, '')) as Location,
CensusTime,
InsertDate
FROM MultiCensusEmail
INNER JOIN app_Location t1 ON MultiCensusEmail.Location = t1.LocationCode
I want it to return a comma delimited list for the locations, but they are showing up on separate rows.
I want the row to end up something like this:
5A8056A7-5D8F-4678-B980-9E54987EE70C | AS EMERGENCY DEPT, BN CARDIAC,
BN CHEST PAIN UNIT | 7:00 | 2016-10-17 9:17:55.067
You don't provide much detail about your data, but I think that your JOIN is not needed.
SELECT AlertID,
(STUFF((SELECT ', ' + t2.LocationDesc
FROM app_Location t2
WHERE MultiCensusEmail.Location = t2.LocationCode // probably you want another condition here
FOR XML PATH (''))
, 1, 1, '')) as Location,
CensusTime,
InsertDate
FROM MultiCensusEmail
What do you want to "group by" (e.g. what data item does have multiple locations)?
The "outer" query should produce the wanted rows without "location" (in your case), and the "inner" FOR XML query should have a condition that filters the "locations" you want to have comma-separated.
I was able to accomplish what I wanted to do using COALESCE:
declare #Location varchar(max)
select #Location = COALESCE(#Location + ', ', '') + LocationDesc
From app_Location INNER JOIN MultiCensusEmail ON MultiCensusEmail.Location = app_Location.LocationCode
where upper(UserID) = 'test'
select distinct AlertID, #Location, CensusTime, InsertDate
from MultiCensusEmail
where upper(UserID) = 'test'
Here in my app I have problems, and a list of people who faced them. Today I'm retrieving all people names through STUFF function like the sample below:
select problem.*,
(
STUFF
(
(
SELECT TOP(3)', ' + person.name
FROM
problem_person
LEFT JOIN person ON problem_person.personId = person.Id
WHERE
problem_person.problemId = problem.Id
order by person.name
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
) as peopleWhoFaced from problem
However, when a lot of people face the same problem, peopleWhoFaced field gets huge. How to retrieve something like Person 1, Person 2 and 36 more faced the problem ? I know that I could do this at API-level, but I'm trying to avoid doing so, and keep API code clean.
How could I accomplish that? Will I need a cursor or something like that?
Thank you in advance.
Append COUNT(*) - 3:
DECLARE #count int = (SELECT COUNT(*) - 3
FROM problem
LEFT JOIN person
ON problem.problemId = person.problemId
INNER JOIN
problem_person
ON problem_person.personId = person.Id)
select problem.*,
(
STUFF
(
(
SELECT TOP(3)', ' + person.name
FROM
problem_person
LEFT JOIN person ON problem_person.personId = person.Id
WHERE
problem_person.problemId = problem.Id
order by person.name
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
) + CASE WHEN #count > 0 THEN N' and ' + CAST(#count as NVARCHAR(20)) + N' more faced the problem' ELSE N'' END
) as peopleWhoFaced from problem
I am having a tricky time doing this so hopefully someone can help. This is what I want my end result to be:
SELECT 'PRODUCT' AS ItemType,
'x' + CAST(MB_StaticOrderProducts.Quantity AS varchar(50)),
MB_StaticOrderProducts.ProductName + ' (' + CAST((MB_StaticOrderProducts.ProductSize) AS varchar(50)) + ' ' + MB_StaticProductMeasure.Value + ')' AS Name,
MB_StaticOrderProducts.ProductSizeID,
GTIN as BarCode
FROM
MB_StaticOrderProducts
INNER JOIN MB_StaticOrderVersions ON MB_StaticOrderProducts.StaticOrderVersionId = MB_StaticOrderVersions.StaticOrderVersionId
INNER JOIN MB_StaticProductMeasure ON MB_StaticOrderProducts.StaticProductMeasureId = MB_StaticProductMeasure.StaticProductMeasureId
Inner Join ProductVariantAttributeCombination pvac on (pvac.Id = (select id from (select Id, cast(AttributesXml as xml) data from ProductVariantAttributeCombination) d cross apply data.nodes('//ProductVariantAttributeValue[Value[1] = 32]') data(d)))
WHERE
MB_StaticOrderProducts.StaticOrderVersionId = '8D803EAE-2CFC-455C-9CE7-0849618E1548'
I would like the column, MB_StaticOrderProducts.ProductSizeId to be in the 4th line of the From section, ProductVariantAttributeCombination, where the number 32 is. Is there a way to use the variable in that area?
For those that ever need it. I changed the data.nodes line to be:
data.nodes( '//ProductVariantAttributeValue[Value[1]
=sql:column("MB_StaticOrderProducts.ProductSizeID")]')
and all worked. Thanks.
Use the Concat function
Like this:
data.nodes( concat('//ProductVariantAttributeValue[Value[1] = ',
MB_StaticOrderProducts.ProductSizeId,
']')