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.
Related
I want to get a list of comma separated customer names. The below code only returns the last name
DECLARE #vfirstname NVARCHAR(500), #vdelimiter NVARCHAR(1)
SET #vdelimiter=','
SELECT #vfirstname = FirstName + #vdelimiter
FROM dbo.Customer c
SET #vfirstname = LEFT(#vfirstname, LEN( #vfirstname ) - 1);
PRINT #vfirstname
I was able to fix it introducing the below statements (with help from google):
SET #vfirstname =''
SELECT #vfirstname = #vfirstname + FirstName + #vdelimiter
FROM dbo.Customer c
But I am unable to understand the need to do this , how does the select statement really work in this scenario?
This will do what you need without the substring function, the
Select ',' is your delimiter
The stuff function removes the first comma/delimiter from the list for you using the XML path
-- use stuff instead of substringb
Select STUFF((
SELECT ',' + FirstName
FROM dbo.Customer
FOR XML PATH('')
), 1, 1,'')
FROM dbo.Customer
-- if you want a space after comma, need to update the STUFF to be 1, 2
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
If I use SQLCommand, I usually need something like:
INSERT INTO klant(klant_id,naam,voornaam) VALUES(#param1,#param2,#param3)";
Is there some easy way I can generate this string?
SSMS generate something like this
,[years]
,[source]
,[TimeStamp])
VALUES
(<count, int,>
,<sex_male, bit,>
,<Ethnicity, tinyint,>
Can I use it somehow?
If you need this frequently then consider SSMS tools pack. This generates CRUD according to user specified templates.
An adhoc not particularly robust alternative is pretty simple with find and replace though.
SSMS generates something like
INSERT INTO [HumanResources].[Employee]
([BusinessEntityID]
,[NationalIDNumber]
,[LoginID]
,[CurrentFlag]
,[rowguid]
,[ModifiedDate])
VALUES
(<BusinessEntityID, int,>
,<NationalIDNumber, nvarchar(15),>
,<LoginID, nvarchar(256),>
,<CurrentFlag, Flag,>
,<rowguid, uniqueidentifier,>
,<ModifiedDate, datetime,>)
Then copy the top section down to the bottom
INSERT INTO [HumanResources].[Employee]
([BusinessEntityID]
,[NationalIDNumber]
,[LoginID]
,[CurrentFlag]
,[rowguid]
,[ModifiedDate])
VALUES
([BusinessEntityID]
,[NationalIDNumber]
,[LoginID]
,[CurrentFlag]
,[rowguid]
,[ModifiedDate])
And select the bottom section and replace [ with # and ] with an empty string.
Or alternatively it would be fairly trivial to write something that queries sys.columns and generates the desired string.
(Again a not robust solution that assumes you are using column names conforming to the rules for standard identifiers- quotename would help with the column names but not the parameter names if you aren't.)
DECLARE #QualifiedName NVARCHAR(500) = '[HumanResources].[Employee]';
WITH C
AS (SELECT *
FROM sys.columns
WHERE object_id = object_id(#QualifiedName)
AND is_computed = 0
AND is_identity = 0)
SELECT '
INSERT INTO ' + #QualifiedName + '
(' + SUBSTRING((SELECT ',' + name
FROM C
ORDER BY column_id
FOR XML PATH('')), 2, 8000) + ')
VALUES
(' + SUBSTRING((SELECT ',#' + name
FROM C
ORDER BY column_id
FOR XML PATH('')), 3, 8000) + ')
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')
Here the code from my function:
-- Get Country Names
DECLARE getCountriesName CURSOR FOR
SELECT c.Name
FROM VocabCountry c
RIGHT OUTER JOIN ProjectCountryRelations cr
ON cr.CountryId = c.Id
WHERE
c.Id = #project_id;
-- Finally Create list to return
OPEN getCountriesName;
FETCH NEXT FROM getCountriesName INTO #Name;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #listOfItems = #listOfItems + #Name + ', '
FETCH NEXT FROM getCountriesName INTO #Name;
END;
CLOSE getCountriesName;
DEALLOCATE getCountriesName;
I am expecting a list of comma separated values, for example, like so:
Canada, United States of America,
I verified that the SELECT returns the countries expected.
Thanks for any help!
Eric
If you're on SQL Server 2008 or newer, you could easily do this with a single SELECT and some FOR XML PATH magic :-)
SELECT
STUFF(
(SELECT ',' + c.Name
FROM VocabCountry c
RIGHT OUTER JOIN ProjectCountryRelations cr
ON cr.CountryId = c.Id
FOR XML PATH('')
), 1, 1, '')
That should return a comma-separated list of those country names for you. No ugly and awful cursor needed!
Using the FOR XML PATH will concat the values with commas.
Using the STUFF Function will remove the first comma you don't want.
So use this:
SELECT
STUFF(
(SELECT ',' + c.Name
FROM VocabCountry c
RIGHT OUTER JOIN ProjectCountryRelations cr
ON cr.CountryId = c.Id
WHERE cr.Id = #project_id
FOR XML PATH('')
), 1, 1, '');
See this fiddle: http://sqlfiddle.com/#!3/fd648/21