Surrounding query with parenthesis cause error For XML - sql-server
When trying to wrap query for further processing I get an error by just putting parenthesis around the query. See query below, if I simply remove the wrapping parenthesis, the query works. But when I use the parenthesis I get this error:
Incorrect syntax near the keyword 'for'
(
select '; ' + [NAME]
from (select a.[NAME] as 'NAME'
from [MS].[dbo].[A_POSITIONS] a
where a.ID = 208418
except
select top 1 b.[NAME]
from [MS].[dbo].[A_POSITIONS] b
where b.ID = 208418) as c
for XML PATH(''),TYPE
)
Anyone have an idea on why this is happening?
Thanks!
Adding the parenthesis alone around your query leads to an error, but if you type a SELECT before the opening parenthesis the code will run, meaning that you can use it for further processing:
if OBJECT_ID('A_POSITIONS') is not null
drop table [dbo].[A_POSITIONS]
create table [dbo].[A_POSITIONS]([ID] int,[Name] varchar(100))
insert into [dbo].[A_POSITIONS] values
(208418, 'one'),(208418, 'two'),(208418, 'three'),(208418, 'four'),(208418, 'five')
select
(
select '; ' + [NAME]
from (select a.[NAME] as 'NAME'
from [MS].[dbo].[A_POSITIONS] a
where a.ID = 208418
except
select top 1 b.[NAME]
from [MS].[dbo].[A_POSITIONS] b
where b.ID = 208418) as c
for XML PATH(''),TYPE
)
One last consideration: TOP keyword without an ORDER BY clause is non-deterministic.
From Microsoft Docs (more info here):
When TOP is used in conjunction with the ORDER BY clause, the result set is limited to the first N number of ordered rows; otherwise, it returns the first N number of rows in an undefined order
So you should really consider adding an ORDER BY to the second part of your query:
select '; ' + [NAME]
from (select a.[NAME] as 'NAME'
from [MS].[dbo].[A_POSITIONS] a
where a.ID = 208418
except
select top 1 b.[NAME]
from [MS].[dbo].[A_POSITIONS] b
where b.ID = 208418
--Add an ORDER BY clause here
) as c
for XML PATH(''),TYPE
Related
csv from subquery in IN() causes conversion error
CROSS APPLY ( SELECT ISNULL( ( SELECT SUM (R.CALORIE) FROM TA_RECIPE AS R WHERE R.NO_RECIPE IN ([mp].recipe_ids) OR R.NO_RECIPE IN ([tags2].recipe_ids) ), 0 ) AS caloriePerPortion ) AS [CAL] The problem is in the part R.NO_RECIPE IN ([mp].recipe_ids) OR R.NO_RECIPE IN ([tags2].recipe_ids) The recipe_ids contain comma seperated lists when there's only one id in the recipe_ids it works fine but if there is actually a list in recipe_ids sql server interprets this as a varchar instead of a list of integers wrapping them in STRING_SPLIT causes the query to become very slow (adds seconds to the execution time)
wrapping them in STRING_SPLIT causes the query to become very slow But that's the only way it can work. select * from t where c in ('1,2,3,4,5') just doesn't do what you want.
the data isn't stored as csv but was retrieved like that throug cross apply with for xml path I changed it to SELECT DISTINCT MM.MAP_ID AS mapId, MM.MENU_ID AS menuId, stuff((select ',' + CAST(RECIPES.recipe_ids AS VARCHAR(MAX)) for xml path('')), 1, 1, '') AS planningRecipe_ids FROM MM LEFT JOIN MP ON MM.MENU_ID = MP.MENU_ID LEFT JOIN RECIPES ON RECIPES.PLANNING_MENU_ID = MP.PLANNING_MENU_ID but then the for xml path doesn't work
Exec into temp table without columns as they are dynamic
I'm working on pivot functionality, where the pivot columns comes dynamically. All the pivot columns I needs to count and display separate column in pivot select statement itself. SELECT CurriculumSegment,attendancedate,section,Class,count(*) as TotalWorkingDays into #NewTempWithTotalDaysCount FROM #temp1 group by CurriculumSegment,attendancedate,Section,Class order by CurriculumSegment, attendancedate,Class,Section SELECT CurriculumSegment,attendancedate,section,Class,count(*) as CountOfPresentDays into #NewTempWithTotalPresentDaysCount FROM #temp1 where attendance='P' group by CurriculumSegment,attendancedate,Section,Class order by CurriculumSegment, attendancedate,Class,Section select a.AttendanceDate,a.Class,a.CurriculumSegment, a.Section,a.TotalWorkingDays,b.CountOfPresentDays,(a.TotalWorkingDays - b.CountOfPresentDays) as TotalAbsentDays, (b.CountOfPresentDays * 100)/a.TotalWorkingDays as PercentOfPresentDays into #TempWithTotalDaysCount from #NewTempWithTotalDaysCount a left outer join #NewTempWithTotalPresentDaysCount b on a.AttendanceDate =b.AttendanceDate and a.CurriculumSegment = b.CurriculumSegment and a.Section= b.Section and a.Class = b.Class -- Query 1 select sum(TotalWorkingDays) as TotalCount,sum(TotalAbsentDays) as AbsentCount,sum(CountOfPresentDays) as PresentCount,curriculumsegment,section,class from #TempWithTotalDaysCount group by class,curriculumsegment,section SET #query = 'SELECT [CurriculumSegment],Class,section,'+#cols+' FROM ( SELECT [CurriculumSegment], Class,section,PercentOfPresentDays,AttendanceDate FROM #TempWithTotalDaysCount) AS up PIVOT (MAX(PercentOfPresentDays) FOR AttendanceDate IN ('+#cols+')) AS pvt' -- Query 2 EXEC (#query) From the query 1 and query 2 results, I needs to do join and get the TotalCount, AbsentCount, PresentCount in the result of query 2. Is it possible to put "EXEC(#query)" in temp table ? I tried but I'm getting invalid object. Because I cant give the column names as they come dynamically form pivot. So,is there any other approach ? Thank you. Find out my result in below image:
Invalid object name in a XML Path / Stuff combination
I am trying to get some values from different rows into a single column, and I keep getting this error : Invalid object name 't' The query is rather big and complicated so I narrowed it down to a simple part that still gives me the error. select IDs = stuff( ( select ',' + convert(varchar, t2.ChassisID) from t as t2 where t2.ChassisID = 42 --t.ChassisID for XML path('') ) , 1, 1, '' ) from ( select ch.ChassisID, p.GPS from tblChassis ch inner join tblPlace p on ch.BestemmingID = p.PlaceID ) t group by t.Gps I tried changing the where clause to a fixed number (42) instead of t.ChassidID and still get the error, so there is only one place left that could cause the error I assume, but I cant see why. I probably am missing something simple but I just cannot see it. What is wrong with this query ? I am using Sql Server 2014
Try declaring your filtered table in a CTE, then referencing this CTE both times. ;WITH FilteredChassis AS ( select ch.ChassisID, p.GPS from tblChassis ch inner join tblPlace p on ch.BestemmingID = p.PlaceID ) select t.Gps, IDs = stuff( ( select ',' + convert(varchar, t2.ChassisID) from FilteredChassis as t2 where t2.Gps = t.Gps for XML path('') ) , 1, 1, '' ) from FilteredChassis AS t group by t.Gps I've made the link through gps, I believe that's what you need.
Searching stored procedure and views but ignoring comments
I have a query as select definition from sys.objects so join sys.sql_modules ssmsp on so.[object_id] = ssmsp.[object_id] where so.type in ('v', 'p') where definition like '%exec%' While populating records, gets populated from comments also. How can I avoid getting filtered from comments? Is there any solution? Thanks
I think this is going to be nearly impossible to achieve in a single query. Bear in mind that [definition] has no formatting, no line breaks, etc. the code is a single line (copy one and paste it into the editor). If a comment starts with -- then where does it end? you have no way of knowing. It is a little easier with /* because you can find the corresponding */ but there is still the added complication of multiple occurrences of the search string. You might have a little more luck using PATINDEX and specifying a case-sensitive version of your collation (if you have a case insensitive database) and for example you know you only want occurrences of EXEC and not "execute" e.g. WHERE patindex('%EXEC%',defintion COLLATE SQL_Latin1_General_CP1_CS_AS) > 0
First for a fast varchar(max) string "splitter". Below is a hacked version of Jeff Moden's delimitedSplit8K. IF OBJECT_ID('dbo.DelimitedSplit2B','IF') IS NOT NULL DROP FUNCTION dbo.DelimitedSplit2B; GO CREATE FUNCTION dbo.DelimitedSplit2B ( #pString varchar(max), #pDelimiter char(1) ) RETURNS TABLE WITH SCHEMABINDING AS RETURN WITH L1(N) AS ( SELECT N FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0), (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) t(N) ), --216 values cteTally(N) AS ( SELECT 0 UNION ALL SELECT TOP (DATALENGTH(ISNULL(#pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM L1 a CROSS JOIN L1 b CROSS JOIN L1 c --2,176,782,336 rows: enough to handle 2,147,483,647 characters (the varchar(max) limit) ), cteStart(N1) AS ( SELECT t.N+1 FROM cteTally t WHERE (SUBSTRING(#pString,t.N,1) = #pDelimiter OR t.N = 0) ) SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1), Item = SUBSTRING(#pString,s.N1,ISNULL(NULLIF((LEAD(s.N1,1,1) OVER (ORDER BY s.N1) - 1),0)-s.N1,DATALENGTH(ISNULL(#pString,1)))) FROM cteStart s; Next for the function to search your DDL create function dbo.SearchObjectDDLFor (#searchstring varchar(100), #maxLen int) returns table as return select objectName, lineNumber, lineText from ( select objectName = ss.[name]+'.'+so.[name], lineNumber = itemnumber, lineText = substring(t.item, 1, isnull(nullif(charindex('--', t.item),0)-1, 8000)), isLongComment = sum ( -- this will assign a 1 for everything case when t.item like '/*%' then 1 when t.item like '*/%'then -1 else 0 end ) over (partition by so.[name] order by itemnumber) from sys.objects so join sys.sql_modules ssmsp on so.[object_id] = ssmsp.[object_id] join sys.schemas ss on so.schema_id = ss.schema_id cross apply dbo.delimitedSplit2B(definition, char(10)) cross apply (values (rtrim(ltrim(replace(item,char(13),''))))) t(item) where so.type in ('v', 'p') and len(definition) < isnull(#maxLen,100000) -- character limit is #maxLen (100K default) ) splitLines where isLongComment = 0 and lineText not like '--%' and lineText <> '*/' and lineText like '%'+#searchstring+'%'; This function: Accepts an input string to search for (#searchstring) Splits your objects into lines Returns only the portions of the line not part of a comment filters the lines created in step3 for ones that contain #searchstring and returns the ObjectName (.), Line number and Text. Caveats: I just threw this together quick so forgive any errors A t-sql splitter that accepts [n]varchar(max) will be slow. A CLR splitter would likely be faster but we're not talking about millions of rows. That said, you can speed it up by filtering the number of lines with #maxLen. #maxlen says "ignore and objects with more that #maxLen number of lines." When null it will search objects up to 100K lines long (but this can be adjusted). This function address comments scenarios where comments look have "--" any where in the string: and scenarios where the comment is nested between "/" and "\ on separate lines. a few scenarios which require more coding to suppress the comments include: . select col1, /* skipping col2 for now */ col3, col4 and /********* comments here *********/ Examples: select * from dbo.SearchObjectDDLFor('nocount', NULL); select * from dbo.SearchObjectDDLFor('nocount', 2000); Results will look something like :
SQL: How to CONCAT value
How can I return the values of MainEmail in the query below, delimited by commas and still count MDCselect? declare #MainHospital varchar(50)='hospital 1' select distinct mainhospital , f.Item, count(*) Count from SurveyPicList s cross apply splitstrings(s.MDCselect,':') as f WHERE MainHospital = #MainHospital GROUP BY MainHospital, f.Item ORDER BY Count DESC To be clear the above returns this: http://i.imgur.com/F1oPU6P.jpg So there were 3 separate entries/people that selected "02-Eye". I want to list out their emails(MainEmail) comma delimited. Please let me know if I am unclear.
Assuming from your use of CROSS APPLY that you are using SQL Server, and that it is at least version 2005, you can use XML to do the concatenation as follows: declare #MainHospital varchar(50)='hospital 1'; select mainhospital , f.Item, count(*) Count ,Stuff( (select distinct ', ' + m.MainEmail from SurveyPicList m where m.MainHospital = #MainHospital and ':' + m.MDCselect + ':' like '%:' + f.Item + ':%' FOR XML PATH ('')), 1, 2, '') as Emails from SurveyPicList s cross apply splitstrings(s.MDCselect,':') as f WHERE MainHospital = #MainHospital GROUP BY MainHospital, f.Item ORDER BY Count DESC From the name I am assuming that splitstrings splits its first argument into items separated by its second argument. Hence I used like to check for f.Item in m.MDCselect in the WHERE condition of the subselect. Actually, what this WHERE condition is doing is collecting all the rows from another instance of the same table that match one record in the final grouped output.