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,
']')
Related
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.
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.
The below query taking more time to give results. This query in running inside the exists clause and also this query having stuff function.Is there any way to optimize or rewrite this query?.
AND EXISTS(SELECT 1
FROM
(SELECT DISTINCT
F_ALIAS,
F_DATA_CODE,
STUFF((SELECT ', ' + A.F_DATA
FROM T_REP_DATA A
WHERE A.F_ALIAS = RPDS.F_ALIAS
AND A.F_DATA_CODE = RPDS.F_DATA_CODE
AND '1:WVTST{PROD006' = A.F_ALIAS
FOR XML PATH(''), TYPE).value( '.', 'NVARCHAR(MAX)'), 1, 2, '') F_DATA
FROM T_REP_DATA RPDS
INNER JOIN
(SELECT DISTINCT F_CUSTOM2
FROM T_MSDSTYPES
WHERE (F_CUSTOM2 IS NOT NULL AND F_CUSTOM2 != '')) MT ON MT.F_CUSTOM2 = RPDS.F_DATA_CODE and RPDS.F_ALIAS = '1:WVTST{PROD006') RPDS_CUSTOM2)
WHERE RPDS_CUSTOM2.F_DATA LIKE 'MANU'
Your query is probably not correct at all (LIKE 'MANU' actually means = 'MANU'), but perhaps your query is doing (or is supposed to be doing) nothing more than this:
AND EXISTS(
SELECT 1
FROM T_REP_DATA RPDS
INNER JOIN T_MSDSTYPES MT
ON MT.F_CUSTOM2 = RPDS.F_DATA_CODE
WHERE RPDS.F_ALIAS = '1:WVTST{PROD006'
AND RPDS.F_DATA = 'MANU'
)
more specific answer requires more details.
Can you give me some pointers (or point in the right direction on what search terms for google)? In a stored procedure I have a parameter #TAG (string). I receive '(14038314,14040071)' (for example) from another application that cannot be altered. In the stored procedure, I need to split apart '(14038314,14040071)' to put quotes around each string value, rebuild it, strip out the outer quotes,strip out the parens and pass it to #TAG in the query below so that it looks like the line commented out below?
SELECT
V.NAME AS VARIETY, TAGID
FROM
mfinv.dbo.onhand h
INNER JOIN
mfinv.dbo.onhand_tags t on h.onhand_id = t.onhand_id
INNER JOIN
mfinv.dbo.onhand_tag_details d on t.onhand_tag_id = d.onhand_tag_id
INNER JOIN
mfinv.dbo.FM_IC_PS_VARIETY V ON V.VARIETYIDX = d.VARIETYIDX
LEFT JOIN
mfinv.dbo.FM_IC_TAG TG ON TG.TAGIDX = t.TAGIDX
WHERE
h.onhand_id = (SELECT onhand_id FROM mfinv.dbo.onhand
WHERE onhand_id = IDENT_CURRENT('mfinv.dbo.onhand'))
AND TG.ID IN (#TAG)
--AND TG.ID IN ('14038314','14040071')
You can Use Dynamic SQL Like This
DECLARE #TAG Nvarchar(MAX)='14038314,14040071'
set #TAG=''''+REPLACE(#TAG,',',''',''')+''''
--select #TAG
DECLARE #SQL NVARCHAR(MAX)=N'
Select V.NAME AS VARIETY, TAGID
FROM mfinv.dbo.onhand h
INNER JOIN mfinv.dbo.onhand_tags t on h.onhand_id = t.onhand_id
INNER JOIN mfinv.dbo.onhand_tag_details d on t.onhand_tag_id = d.onhand_tag_id
INNER JOIN mfinv.dbo.FM_IC_PS_VARIETY V ON V.VARIETYIDX = d.VARIETYIDX
LEFT JOIN mfinv.dbo.FM_IC_TAG TG ON TG.TAGIDX = t.TAGIDX
WHERE h.onhand_id = (SELECT onhand_id FROM mfinv.dbo.onhand
WHERE onhand_id = IDENT_CURRENT (''mfinv.dbo.onhand''))
AND TG.ID IN ('+#TAG+')'
PRINT #SQL
EXEC (#SQL)
Here's what I did. Thank you all for responding. Thanks to dasblinkenlight for answering "How to replace first and last character of column in sql server?". Thanks to SQLMenace for answering "How Do I Split a Delimited String in SQL Server Without Creating a Function?".
Here's how I removed parenthesis:
#Tag nvarchar(256)
SET #Tag = SUBSTRING(#Tag, 2, LEN(#Tag)-2)
Here's how I split and rebuilt #Tag:
AND TG.ID in
(
SELECT SUBSTRING(',' + #Tag + ',', Number + 1,
CHARINDEX(',', ',' + #Tag + ',', Number + 1) - Number -1)AS VALUE
FROM master..spt_values
WHERE Type = 'P'
AND Number <= LEN(',' + #Tag + ',') - 1
AND SUBSTRING(',' + #Tag + ',', Number, 1) = ','
)
Query for treeview control, sometimes contains empty elements which throws an exception (when there are no attributes in an element) due to data-binding of the control the text values is set to "GrandChildOfFirstRow"
I did get rid of them in my query via xquery but is there an alternative way to doing this or a better smarter way to get rid of those empty elements, (I need the left outer join for proper records for this query) or is it possible to combine the xquery code into shorter code:
Query:
declare #x as xml
set #x =
(
SELECT distinct
Table1.AssetObjID, Table1.Asset_ID , Table1.FromLR, Table1.AssetType + ', ' + Table1.StreetName + ', ' + Table1.FromMunicNo as FirstRow,
Table2.ACIObjID ,Table2.PAssetObjID, Table2.Feature_ID + ', ' + Table2.FeatureName AS ChildOfFirstRow,
Table3.ITMObjID ,Table3.Item_ID + ',' + Table3.[DESC] as GrandChildOfFirstRow
FROM Table1 left outer join
Table2 ON Table1.AssetObjID = Table2.PAssetObjID left outer join
Table3 ON Table1.AssetObjID = Table3.AssetObjID AND Table2.ACIObjID = Table3.ACIObjID
where Table1.AssetType ='xxxx'
for xml auto,root('xml')
)
--what it does is it only grabs one empty element and deletes only occurrences of that
--specific element for the whole file
--so If I have 2 or more elements which are empty in an xml file
--I will have to repeat that code each time
SET #x.modify('delete //*[not(node()) and not(./#*)]')
SET #x.modify('delete //*[not(node()) and not(./#*)]')
You can use for xml path() and build your nested levels with correlated sub-queries.
select Table1.AssetObjID as "#AssetObjID",
Table1.Asset_ID as "#Asset_ID",
Table1.FromLR as "#FromLR",
Table1.AssetType + ', ' + Table1.StreetName + ', ' + Table1.FromMunicNo as "#FirstRow",
(
select Table2.ACIObjID as "#ACIObjID",
Table2.PAssetObjID as "#PAssetObjID",
Table2.Feature_ID + ', ' + Table2.FeatureName AS "#ChildOfFirstRow",
(
select Table3.ITMObjID as "#ITMObjID",
Table3.Item_ID + ',' + Table3.[DESC] as "#GrandChildOfFirstRow"
from Table3
where Table1.AssetObjID = Table3.AssetObjID and
Table2.ACIObjID = Table3.ACIObjID
for xml path('Table3'), type
)
from Table2
where Table1.AssetObjID = Table2.PAssetObjID
for xml path('Table2'), type
)
from Table1
where Table1.AssetType = 'xxxx'
for xml path('Table1'), root('xml')