Returning comma separated values in SQL Server in one element - sql

I have the below query which I am using to return comma separated result.
SELECT STUFF
(
(
SELECT ',' + em.EMAIL
FROM(
SELECT DISTINCT USR.EMAIL AS EMAIL
FROM PRNCPLS A, PRNCPLS B, USER_INFO USR,
RELATIONSHIPS C
WHERE A.ID = C.PARENTID
AND B.ID = C.CHILDID
AND A.TYPE = 'USER' and B.TYPE = 'ROLE'
AND A.ID = USR.ID
and B.NAME = 'Approver'
AND USR.EMAIL IS NOT NULL) em
ORDER BY em.EMAIL FOR XML PATH('')
),
1, 1, ''
) AS Output
I have a requirement to update this query in a way that the first line of the SQL statement (and not the output) always start like this
SELECT EMAIL FROM
This is required since the tool I am using for some reason expects FROM in the first line and just one single element in the SELECT clause. My query actually only returns one element, so I was hoping to somehow update it.
Expected output - abcd#gmail.com,1234#yahoo.com,xyz#gmail.com
Any help would be appreciated.

SELECT EMAIL FROM (
SELECT STUFF
(
(
SELECT ',' + em.EMAIL
FROM(
SELECT DISTINCT USR.EMAIL AS EMAIL
FROM PRNCPLS A, PRNCPLS B, USER_INFO USR,
RELATIONSHIPS C
WHERE A.ID = C.PARENTID
AND B.ID = C.CHILDID
AND A.TYPE = 'USER' and B.TYPE = 'ROLE'
AND A.ID = USR.ID
and B.NAME = 'Approver'
AND USR.EMAIL IS NOT NULL) em
ORDER BY em.EMAIL FOR XML PATH('')
),
1, 1, '') AS EMAIL
) AS Output
Beware of both "...EMAIL...":
"SELECT EMAIL ..."
"...1,1,'') AS EMAIL...".

have you tried
SELECT 'SELECT EMAIL FROM ' + STUFF
(
(
SELECT ',' + em.EMAIL
FROM(
SELECT DISTINCT USR.EMAIL AS EMAIL
FROM PRNCPLS A, PRNCPLS B, USER_INFO USR,
RELATIONSHIPS C
WHERE A.ID = C.PARENTID
AND B.ID = C.CHILDID
AND A.TYPE = 'USER' and B.TYPE = 'ROLE'
AND A.ID = USR.ID
and B.NAME = 'Approver'
AND USR.EMAIL IS NOT NULL) em
ORDER BY em.EMAIL FOR XML PATH('')
),
1, 1, ''
) AS Output;
or is there more to how the data is formatted?

Have you tried doing
SELECT 'SELECT EMAIL FROM '
UNION
... Your existing query

You can wrap almost any SELECT like this:
SELECT t.SomeColumn FROM
(
place your existing SELECT here
) t;
This would not work with a CTE-query, but CTEs can be shifted into sub-queries themselves.
Hint: Try to avoid old-fashioned JOINs if possible. There is a good link provided by Sami in the comments...

Related

(Group By) & (FOR XML PATH) & JOIN

Is there any other approch rather than saving the result of joining (the Table #VT & TableA ) in one Table variable and then from there make the Grouping
select ID ,
STUFF (( select distinct ' / ' + TA.Reason
from #VT
where ( ID = VT.ID )
for xml path(''),TYPE).value('(./text())[1]','VARCHAR(MAX)') ,1,2,'' ) as XXX
from #VT as VT
join TableA as TA on ( TA.ID = VT.ID)
group by ID
I get this Error
Column 'TableA.Reason' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I would go with DISTINCT instead of GROUP BY :
SELECT DISTINCT ID,
STUFF (( SELECT DISTINCT ' / ' + ta.Reason
FROM TableA ta
WHERE vt.ID = ta.ID
FOR XML PATH (''),TYPE).VALUE('(./text())[1]','VARCHAR(MAX)'
), 1, 2, ''
) AS XXX
FROM #VT vt;
I think you have the tables in the wrong place. Does this work?
select ID ,
stuff(( select distinct ' / ' + TA.Reason
from TableA TA
where vt.ID = ta.ID
for xml path(''), TYPE
).value('(./text()) [1]', 'VARCHAR(MAX)') , 1, 2, ''
) as XXX
from #VT vt ;

How to add a temp table in SQL server

I am trying to add a temp table to my query so that I can query that temp table, I have searched the internet but I couldn't get a solution.
this is my query
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
which gives me the following when I run it
ID | Name
1111 | BaseBall
2222 |BasketBall
45896 |Relay
now I tried to create a temp table as follows
Create Table #temp(
ID int,
Name varchar
)
;WITH cte AS (
SELECT ID, g.Name
FROM game.Game g WITH(NOLOCK)
WHERE ID IN (SELECT Data FROM system.Split(1, ','))
UNION ALL
SELECT g.ID, g.Name
FROM game.Game g WITH(NOLOCK)
JOIN cte ON g.ParentID = cte.ID
)
insert into #temp // i wanted to set these values in the temp table
SELECT c.ID,
c.Name
FROM cte c
INNER JOIN list.Type gt WITH(NOLOCK) ON c.TypeId = gt.TypeID
WHERE c.ID NOT IN (SELECT Data FROM system.Split(1, ','))
AND c.ID IN (SELECT ID FROM game.code WITH(NOLOCK)
WHERE ID = c.ID
AND StatusCode IN ('OP', 'CL', 'SU')
AND isDisplay = 'True'
AND GETDATE() BETWEEN DisplayStart AND DisplayEnd
AND GETDATE() < ISNULL(ResultDateTime, ResultExpected)
)
every time I try to store this information in the temp table it gives me an error 'Column name or number of supplied values does not match table definition.' But I only have two values in. What am I doing wrong that I cant see?
First, why not just use select into?
IF OBJECT_ID('TempDB..#temp') IS NOT NULL
BEGIN
DROP TABLE #temp
END
select c.ID, c.Name
into #temp
from . . .
Then you don't need to define #temp as a table.
Next, your definition is bad, because Name has only one character. This would be fixed with select into.
However, I don't know why you are getting the particular error you are getting. The numbers of columns appears to match.

SQL Dynamic Pivot Query

I need help with a pivot table if possible. Not sure it can be done. Below is my example.
Questions
Answers
User Answers
Answer Pivot
Thanks For any help.
I have attached a screenshot of db results with the pivot working . The code below pivot as it should and that works fine. If you can look at the column "Subject has exp..." I would like the column repeated three times, The heading is the question, But I also would like each possible answer to shown with the question as well.
Thank Again!
Thansk Again.
Here Is a Sample of the Code:
DECLARE #columns VARCHAR(MAX)
SELECT #columns = COALESCE(#columns + ','+QUOTENAME([QuestionText]),QUOTENAME([QuestionText]))
FROM SchemaWema.vts_vwSurvey INNER JOIN
Question ON SchemaWema.vts_vwSurvey.SurveyID = SchemaWema.vts_vwQuestion.SurveyID
WHERE SchemaWema.vts_vwSurvey.DecisionSetId = 598 AND SchemaWema.vts_vwSurvey.FormType = 1
Set #columns = REPLACE(#columns, '[]', '[No Name Given]')
DECLARE #sql NVARCHAR(MAX)=N' SELECT * FROM
(
SELECT Project.PROJECTNAME, Project.ID,
Sites.PROJECTSTUDYSITENUMBER, Sites.PROJECTSTUDYSITENAME,
Study.PROJECTSTUDYNAME, Study.PROJECTSTUDYNUMBER,
Survey.SurveyID, Question.QuestionID, Cases.SITEID, Cases.EVENTDATE,
Cases.SUBJNO, Cases.EventType, Cases.TriggerEvent,
Cases.DecisionSetID, Cases.PanelID, Cases.RECORDSTATUS,
Project.PROJECTSPONSOR, VoterAnswers.AnswerID, VoterAnswers.VoterID,
VoterAnswers.AnswerText AS FreeTypedAnswers, Voter.VoteDate, Users.SHOWNNAME, Panel.PANELNAME, Sites.COUNTRY,
Cases.VERSIONID, cases.CSID, cases.CASENUMBER,Cases.CASEDATEUPDATED AS LASTUPDATED,
Cases.DECISIONSETNAME,
Question.QuestionText,
CASE
WHEN
CAST(VoterAnswers.AnswerText AS VARCHAR(MAX)) IS NULL OR CAST(VoterAnswers.AnswerText AS VARCHAR(MAX)) = ''''
THEN
Answer.AnswerText
ELSE
CAST(Answer.AnswerText AS VARCHAR(MAX))
END AS AnswerText
FROM
(
SELECT a.ID, a.STUDYID, a.SITEID, a.CSID, a.VERSIONID, a.CASENUMBER, a.CASEINITIALS, a.EVENTDATE, a.CASEDETAILSFILE, a.CASEDETAILSFILEVERSION,
a.CASESTATUS, a.RECORDSTATUS, a.CASEDATEUPDATED, a.PROJECTDATEUPDATED, a.PanelID, a.DecisionSetID, a.SUBJNO, a.EventType, a.TriggerEvent,
a.Priority, a.id1, a.id2, a.dateid, a.dateiddt1, a.dateiddt2, a.extratext1, a.extratext2, SchemaWema.PROJECTPANELDECISIONSETVIEW.DECISIONSETNAME
FROM SchemaWema.PROJECTCASE AS a LEFT OUTER JOIN
SchemaWema.PROJECTPANELDECISIONSETVIEW ON a.DecisionSetID = SchemaWema.PROJECTPANELDECISIONSETVIEW.DECISIONSETID
WHERE (a.CASEDATEUPDATED =
(SELECT MAX(CASEDATEUPDATED) AS Expr1
FROM SchemaWema.PROJECTCASE AS b
WHERE (a.ID = PROJECTID) AND (a.CSID = CASEID) AND (a.VERSIONID = VERSIONID) )) AND (a.RECORDSTATUS <> ''D'')
)Cases
LEFT OUTER JOIN
(
SELECT PROJECTID, PROJECTNAME, PROJECTSPONSOR
FROM SchemaWema.PROJECT AS a
WHERE (PROJECTDATEUPDATED =
(SELECT MAX(PROJECTDATEUPDATED) AS Expr1
FROM SchemaWema.PROJECT AS b
WHERE (a.ID = PROJECTID))) AND (RECORDSTATUS <> ''D'')
) Project on
Project.ID = Cases.ID
LEFT OUTER JOIN
(
SELECT DISTINCT a.ID, a.STUDYID, a.SITEID, a.PROJECTSTUDYSITENAME, a.PROJECTSTUDYSITENUMBER, SchemaWema.PROJECTSTUDYVIEW.PROJECTSTUDYNAME, a.COUNTRY
FROM SchemaWema.PROJECTSTUDYSITE AS a INNER JOIN
SchemaWema.PROJECTVIEW ON a.ID = SchemaWema.PROJECTVIEW.ID INNER JOIN
SchemaWema.PROJECTSTUDYVIEW ON a.ID = SchemaWema.PROJECTSTUDYVIEW.ID AND
a.STUDYID = SchemaWema.PROJECTSTUDYVIEW.STUDYID
WHERE (a.PROJECTSTUDYSITEDATEUPDATED =
(SELECT MAX(PROJECTSTUDYSITEDATEUPDATED) AS Expr1
FROM SchemaWema.PROJECTSTUDYSITE AS b
WHERE (a.ID = PROJECTID) AND (a.STUDYID = STUDYID) AND (a.SITEID = SITEID))) AND (a.RECORDSTATUS <> ''D'')
)Sites on
Cases.SITEID = Sites.SITEID
LEFT OUTER JOIN
(
SELECT DISTINCT PROJECTID, STUDYID, PROJECTSTUDYNAME, PROJECTSTUDYNUMBER, PROJECTSTUDYDESCRIPTION
FROM SchemaWema.PROJECTSTUDY AS a
WHERE (PROJECTSTUDYDATEUPDATED =
(SELECT MAX(PROJECTSTUDYDATEUPDATED) AS Expr1
FROM SchemaWema.PROJECTSTUDY AS b
WHERE (a.ID = PROJECTID) AND (ISNULL(a.STUDYID, ''0'') = ISNULL(STUDYID, ''0'')))) AND (RECORDSTATUS <> ''D'')
)Study on
Study.STUDYID = Cases.STUDYID
inner join
(
SELECT VoterID, UID, SurveyID, ContextUserName, VoteDate, StartDate, IPSource, Validated, ResumeUID, ResumeAtPageNumber, ProgressSaveDate,
ResumeQuestionNumber, ResumeHighestPageNumber, LanguageCode, SurveyStatus, VoteAcceptRejectDate, CaseID, VersionID, PdfFileName, voterSurveyStatus,
dateupdated, recordstatus, modifiedby, changereason
FROM SchemaWema.vts_tbVoter AS a
WHERE (dateupdated =
(SELECT MAX(dateupdated) AS Expr1
FROM SchemaWema.vts_tbVoter AS b
WHERE (a.VoterID = VoterID) AND (a.SurveyID = SurveyID) AND (a.CSID = CaseID) AND (a.VersionID = VersionID)))
) Voter on
Voter.CSID = Cases.CSID
AND Voter.VersionID = Cases.VersionID
Inner Join
(
SELECT DISTINCT SurveyID, DecisionSetId, FormType
FROM SchemaWema.vts_tbSurvey AS a
WHERE (dateupdated =
(SELECT MAX(dateupdated) AS Expr1
FROM SchemaWema.vts_tbSurvey AS b
WHERE (a.SurveyID = SurveyID))) AND (recordstatus <> ''D'')
) Survey on
Survey.SurveyID = Voter.SurveyID
inner Join
(
SELECT DISTINCT
VoterID, AnswerID, SectionNumber, CAST(AnswerText AS varchar(MAX)) AnswerText, SurveyID, CaseID, versionID
FROM SchemaWema.vts_tbVoterAnswers AS a
WHERE (dateupdated =
(SELECT MAX(dateupdated) AS Expr1
FROM SchemaWema.vts_tbVoterAnswers AS b
WHERE (a.VoterID = VoterID) AND (a.AnswerID = AnswerID) AND (a.SectionNumber = SectionNumber) AND (a.SurveyID = SurveyID) AND (a.CSID = CaseID) AND
(a.versionID = versionID))) AND (recordstatus <> ''D'')
)VoterAnswers on
VoterAnswers.SurveyID = Survey.SurveyID
AND VoterAnswers.CSID = Voter.CSID
AND Voter.VoterID = VoterAnswers.VoterID
AND VoterAnswers.versionID = Voter.versionID
AND VoterAnswers.SurveyID = Voter.SurveyID
FULL OUTER JOIN
(
select DISTINCT a.USERID, a.USERNAME, a.FIRSTNAME, a.LASTNAME, a.SHOWNNAME
from SchemaWema.users as a
WHERE (a.userdateupdated =
(SELECT MAX(b.userdateupdated) AS Expr1
FROM SchemaWema.users AS b
WHERE (a.userID = b.userID) ))
AND (a.RECORDSTATUS <> ''D'')
) Users on
VoterAnswers.VoterID = Users.USERID
AND Voter.VoterID = Users.USERID
inner join
(
SELECT DISTINCT AnswerID, QuestionID, AnswerText FROM SchemaWema.vts_tbAnswer AS a
WHERE (dateupdated =
(SELECT MAX(dateupdated) AS Expr1
FROM SchemaWema.vts_tbAnswer AS b
WHERE (a.AnswerID = AnswerID))) AND (recordstatus <> ''D'')
) Answer on
Answer.AnswerID = VoterAnswers.AnswerID
inner Join
(
SELECT DISTINCT QuestionID,SurveyID, QuestionText
FROM SchemaWema.vts_tbQuestion AS a
WHERE (dateupdated =
(SELECT MAX(dateupdated) AS Expr1
FROM SchemaWema.vts_tbQuestion AS b
WHERE (a.QuestionID = QuestionID))) AND (recordstatus <> ''D'')
) Question on
Answer.QuestionID = Question.QuestionID
AND Question.SurveyID = Survey.SurveyID
AND Question.SurveyID = VoterAnswers.SurveyID
inner join
(
SELECT DIStinct
[PANELID] ,[PANELNAME]
FROM [AdjudicateV3].[Adjudicate].[PROJECTPANELVIEW]
)Panel on
Panel.PANELID = Cases.PanelID
WHERE CASEs.ID = ' + #ID + ' AND Survey.DecisionSetId = '+ DeeSetId +' AND Survey.FormType = '+ #Forms +'
) AS SourceTable
PIVOT
(
MAX(AnswerText)
FOR QuestionText IN ('+#columns+')
) AS PivotTable'
It can be done using a dynamic pivot.
First thing you have to do is build the cols you're going to use for the pivot..
declare #cols varchar(max)
select #cols = Coalesce(#cols + ', ', '') + '[' + q.Question + '(' + a.Question + ')]'
from Questions q
join Answers a on q.ID = a.QuestionID
this will concatenate all of the column headers you want into one string like
[What is your favorite Car Color(Blue)], [What is your favorite Car Color(Red)]
putting the column names inside brackets is important here...
The next step is building your pivot query
declare #sql varchar(max)
set #sql = 'Select [User], ' + #cols + ' from (
select ua.[User], ''X'' as Chosen,
q.Question + ''('' + a.Question + '')'' Answer
from UserAnswers ua
join Answers a On ua.AnswerId = a.ID and ua.QuestionID = a.QuestionID
join Questions q on a.QuestionID = q.ID
) t
pivot (
max(Chosen)
for Answer IN (' + #cols + ')
) p'
exec(#sql)
this will create a subquery with three columns User, Chose, Answer.. user is user name, chosen is just an X for every record, and the Answer, which is what is used to pivot. Answer looks like the column names above without the brackets..
next it pivots the subquery.. and selects the Name and dynamic columns..
SQL Fiddle Example

why are the results of the two queries different

the first query:
SELECT u.id , prop1.id
FROM ( SELECT '9fbc6e9b59504c08ac643752c1e2d033' AS id ,
'|6813dbbfec6241a19b8d2316d2cb2a65,1|' AS customprop
UNION
SELECT 'f2271c45682f45fc84527c4afff0ab16' AS id ,
'|6813dbbfec6241a19b8d2316d2cb2a65,2|' AS customprop
) u
INNER JOIN ( SELECT ROW_NUMBER() OVER ( ORDER BY a.Id ) id ,
A.Id propId ,
B.NAME
FROM ( SELECT '6813dbbfec6241a19b8d2316d2cb2a65' AS id ,
CONVERT(XML, '<v>1,职业资格1</v><v>2,职业资格2</v>') AS value
) A
OUTER APPLY ( SELECT Name = N.v.value('.',
'nvarchar(Max)')
FROM A.[VALUE].nodes('/v') N ( v )
) B
) prop1 ON CHARINDEX('|' + prop1.propid + ','
+ CONVERT(NVARCHAR(10), prop1.id)
+ '|', u.customprop) > 0
GROUP BY u.id ,
prop1.id
the second query:
SELECT u.id ,prop1.id, count(*)
FROM ( SELECT '9fbc6e9b59504c08ac643752c1e2d033' AS id ,
'|6813dbbfec6241a19b8d2316d2cb2a65,1|' AS customprop
UNION
SELECT 'f2271c45682f45fc84527c4afff0ab16' AS id ,
'|6813dbbfec6241a19b8d2316d2cb2a65,2|' AS customprop
) u
INNER JOIN ( SELECT ROW_NUMBER() OVER ( ORDER BY a.Id ) id ,
A.Id propId ,
B.NAME
FROM ( SELECT '6813dbbfec6241a19b8d2316d2cb2a65' AS id ,
CONVERT(XML, '<v>1,职业资格1</v><v>2,职业资格2</v>') AS value
) A
OUTER APPLY ( SELECT Name = N.v.value('.',
'nvarchar(Max)')
FROM A.[VALUE].nodes('/v') N ( v )
) B
) prop1 ON CHARINDEX('|' + prop1.propid + ','
+ CONVERT(NVARCHAR(10), prop1.id)
+ '|', u.customprop) > 0
GROUP BY u.id ,
prop1.id
sql can be executed on sqlserver 2005 directly.
the first query can produce one item and the second query produce two items.
I think that the two queries should both produce two items.
I have thouht for three days and I really want to konw why.
I'm a Chinese and my English is poor.I hope you can understand my description
Tough question, but the problem is with this line:
INNER JOIN ( SELECT ROW_NUMBER() OVER ( ORDER BY a.Id ) id ,
The ORDER BY is ambiguous and consequently, if it is executed multiple times (which it can be because of the INNER JOIN it is contained in), it may not always return the same ordering/assignment. This can cause a latter join condition to only match on one record instead of two, which is what happens in the query plan being used for the version without the count(*) column.
To fix this, you just need to add something to make the ordering assignment unique, like this:
INNER JOIN ( SELECT ROW_NUMBER() OVER ( ORDER BY a.Id, B.Name ASC ) id ,
Try it like this, it should work.
Your problem is with the ORDER BY clause of the ROW_NUMBER - since the a.ID is not unique the outcome is unpredictable. Make that unique and your problem will go away - you can use something like
...SELECT ROW_NUMBER() OVER ( ORDER BY newid() ) id...

How to do a Select Distinct when returning XML

I have a a stored procedure that returns an XML, the problem now is that i want it to return distinct ClientID's but when I do this.. it says
The xml data type cannot be selected as DISTINCT because it is not comparable.
How can i do this? here is my Query
SELECT DISTINCT ClientTable.ClientID,
ClientTable.ClientAddress,
ClientTable.RetailStore,
ClientTable.PhoneNumber,
ClientTable.City,
ClientTable.Amount,
(SELECT Rating = IsNull(AVG(Rate), 0),
NumberRates = IsNUll(COUNT(ClientID), 0)
FROM ReviewsTable
WHERE ReviewsTable.ClientID = ClientTable.ClientID
FOR XML PATH(''), TYPE)
FROM ClientTable
INNER JOIN ClientTypes
ON ClientTable.ClientID = ClientTypes.ClientID
WHERE ClientTable.ClientID IN (SELECT myFreeTextTableID
FROM myFreeTextTable
WHERE FREETEXT(*, #Keyword))
OR
ClientTypes.ClientID IN (SELECT myFreeTextTableID
FROM myFreeTextTable
WHERE FREETEXT(*, #Keyword))
ORDER BY ClientTable.Order ASC
FOR XML AUTO, TYPE, ELEMENTS
I'm not even going to try to reproduce your schema or data, but what about this query?
;WITH ft AS
(
SELECT ClientID = myFreeTextTableID
FROM myFreeTextTable WHERE FREETEXT(*, #Keyword)
),
c AS
(
SELECT DISTINCT
c.ClientID,
c.ClientAddress,
c.RetailStore,
c.PhoneNumber,
c.City,
c.Amount,
c.[Order]
FROM dbo.ClientTable AS c
INNER JOIN dbo.ClientTypes AS t
ON c.ClientID = t.ClientID
WHERE EXISTS
(
SELECT 1 FROM ft
WHERE ClientID IN (c.ClientID, t.ClientID)
)
)
SELECT
c.ClientID,
c.ClientAddress,
c.RetailStore,
c.PhoneNumber,
c.City,
c.Amount,
Rating = (SELECT COALESCE(AVG(Rate), 0),
NumberRates = COALESCE(COUNT(ClientID), 0)
FROM ReviewsTable
WHERE ReviewsTable.ClientID = c.ClientID
FOR XML PATH(''), TYPE)
FROM c
ORDER BY c.[Order]
FOR XML AUTO, TYPE, ELEMENTS;