SQL Select COLUMNS in a single row with inner join - sql

Hi I am having problem with selecting my desired output in my program.
Here's the scenario:
I have 2 tables
_Users
_Mobiles
Lets say I have these fields and data in each tables:
_Users
**UserID** **Name**
1 John
2 Mark
_Mobiles
**UserID** **Mobile**
1 44897065
1 44897066
1 44897067
2 45789071
What I know is that I can use
Select a.UserID, b.Mobile
from _Users a INNER JOIN
_Mobiles b ON a.UserID = b.UserID
where UserID = 1
which will retrieve data in this format:
UserID Mobile
1 44897065
1 44897066
1 44897067
but what I want is to arrange the data into:
UserID Mobile1 Mobile2 Mobile3
1 44897066 44897065 44897065
and if another mobile for the same user is encoded, it will output as Mobile4 and so on..
I know this is strange but I want to do it for some reason :D
Is this possible and can anybody help me how to do it. Thank you so much everyone.

try this Sql query..
DECLARE #cols AS NVARCHAR(MAX),#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(a.MobileCategory)
from
(
Select a.UserID as UserID, b.Mobile as Mobile,'Mobile'+ CAST(ROW_NUMBER() OVER( ORDER BY b.Mobile) AS VARCHAR) AS MobileCategory
FROM _Users a INNER JOIN
_Mobiles b ON a.UserID = b.UserID
WHERE a.UserID = 1
) a
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT UserID,' + #cols + ' from
(
Select a.UserID as UserID,b.Mobile as Mobile,''Mobile''+ CAST(ROW_NUMBER() OVER( ORDER BY b.Mobile) AS VARCHAR) AS MobileCategory
FROM _Users a INNER JOIN
_Mobiles b ON a.UserID = b.UserID
WHERE a.UserID = 1
) x
pivot
(
sum(Mobile)
for MobileCategory in (' + #cols + ')
) p '
execute(#query)

This could use help, but something like this
with (
select u.userid, m1.mobid, m2.mobid, .. mN.mobid
from users u
left join mobiles m1
on u.userid=m1.userid
left join mobiles m2
on u.userid=m2.userid
...
left join mobiles mN
on u.userid=mN.userid
) as mobuser
select * from mobuser
where ( m2.mobid>m1.mobid or m2.mobid is null)
and ( m3.mobid>m2.mobid or m3.mobid is null)
...
and (mN.mobid>mNMinus1.mobid or mN.mobid is null)

Related

Convert a column of Rows to only one column column in SQL Server query

I have this query in SQL Server 2012 :
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
The result is like this :
id productid
1 1
1 2
1 3
1 10
2 5
2 1
3 4
3 11
but I want this result :
1 1,2,3,10
2 5,1
3 4,11
How can I get that result ?
Try this:
WITH cte as
(
select
tblplantitle.id, tblplantoproductpayment.productid
from
tblplantitle
inner join
tblplan on tblplan.plantitleid = tblplantitle.id
inner join
tblplantoproductpayment on tblplantoproductpayment.planid = tblplan.id
group by
tblplantitle.id, tblplantoproductpayment.productid
)
SELECT id, productid =
STUFF((SELECT ', ' + productid
FROM cte b
WHERE b.id= a.id
FOR XML PATH('')), 1, 2, '')
FROM cte a
GROUP BY id
Use the below query for the desired output.
SELECT tblplantitle.id
, STUFF((SELECT ', ' + CAST(tblplantoproductpayment.productid AS VARCHAR(10)) [text()]
FROM tblplantoproductpayment
WHERE tblplantoproductpayment.planid = tblplan.id
FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)'),1,2,' ') List_ProductIds
FROM tblplantitle
INNER JOIN tblplan on tblplan.plantitleid = tblplantitle.id
GROUP BY tblplantitle.id

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

SQL Query & unpivot Syntax

I have a permission system that defines users access to certain items.
I need a report page to show members and their access to the items.
The table needs to be like this:
+---------+--------+--------+------+--------+
| Members | Item 1 | Item 2 | .... | Item N |
+---------+--------+--------+------+--------+
| Member1 | x | + | .... | + |
+---------+--------+--------+------+--------+
| Member2 | + | x | .... | + |
+---------+--------+--------+------+--------+
I have a 3 table joined query for listing the members and the items they can access but I could not convert it into pivot syntax.
Select members.id memberID, members.name memberName, items.name as item
From members
Left Join member_permission On memberID = members.id
Left Join items On items.id = member_permission.itemID
This is the not working query I have:
Select memberName, itemName
From (
select members.id, members.name, item.name as itemName
from members
Left Join member_permission On memberID = members.id
Left Join item On item.id = member_permission.itemID
) p
Unpivot
(itemName For name IN (item.name)) as unp
and the error I receive:
The column name "name" specified in the UNPIVOT operator conflicts with the existing column name in the UNPIVOT argument.
I created an example to play with Sqlfiddle
You don't need to use UNPIVOT for this query. UNPIVOT is used to convert multiple columns into multiple rows. You only need to apply the PIVOT function to turn your items into columns.
I would first suggest using a windowing function like row_number() to create your new column headers, then apply the PIVOT function:
select id, name, Item1, Item2, Item3
from
(
select members.id, members.name, items.name as item,
'item'+
cast(row_number() over(partition by members.id
order by members.id) as varchar(10)) col
from members
Left Join member_permission
On memberID = members.id
Left Join items
On items.id = member_permission.itemID
) d
pivot
(
max(item)
for col in (Item1, Item2, Item3)
) piv;
See SQL Fiddle with Demo. Then if you have an unknown number of values your query would need to use dynamic SQL:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME('item'+cast(seq as varchar(10)))
from
(
select row_number() over(partition by memberid
order by memberid) seq
from member_permission
) d
group by seq
order by seq
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT id, name, ' + #cols + N'
from
(
select members.id, members.name, items.name as item,
''item''+
cast(row_number() over(partition by members.id
order by members.id) as varchar(10)) col
from members
Left Join member_permission
On memberID = members.id
Left Join items
On items.id = member_permission.itemID
) x
pivot
(
max(item)
for col in (' + #cols + N')
) p '
execute sp_executesql #query;
See SQL Fiddle with Demo

How can I use Sql to Order By This Statement?

How can I order the list 'widgets_spec by number of widgets?
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,widgets) + '<br> '
from dbo.spec_master m2
where m.p_c_id = m2.p_c_id and widgets is not null
for xml path(''), type).value('.[1]', 'nvarchar(max)'
) as widgets_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
Right now output looks like:
<li>10<br> <li>12<br> <li>15<br> <li>8<br>
When I want it to look like:
<li>8<br> <li>10<br> <li>12<br> <li>15<br>
Thanks for your help.
EDIT: I'm trying to order the internal select statement that concatenates the values.
You do not need both Distinct and Group By. You should use one or the other. In this case, I believe you have to use Group By for it to work.
Select m.p_c_id
, (
Select '<li>' + Cast( m2.num_of_lights As varchar(10)) + '<br /> '
From dbo.spec_master As m2
Where m.p_c_id = m2.p_c_id
And m2.num_of_lights Is Not Null
Group By m2.num_of_lights
Order By m2.num_of_lights
For Xml Path(''), type).value('.[1]', 'nvarchar(max)'
) As numLights_spec
From dbo.spec_master As m
Inner Join dbo.ProductVaration As pv
On pv.p_c_id = m.p_c_id
Inner Join dbo.Varation As v
On v.varation_id = pv.varation_type_id
Where v.varation_id = 4
Group by m.p_c_id
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,num_of_lights) + '<br> '
from dbo.spec_master m2
where m.p_c_id = m2.p_c_id and num_of_lights is not null
ORDER BY convert(varchar,num_of_lights)
) as numLights_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
) As SubA
Some of the other answers here won't work, since ordering by the now-varchar num_of_lights will put '8' after '15' as is happening now. You want to order the numLights numerically, which isn't going to happen with those html tags around them. You can add a subselect to your subselect so that you order them, then select them with the tags around them. Example (not tested):
SELECT * FROM (
select distinct
m.p_c_id
,(select distinct '<li>' +convert(varchar,num_of_lights) + '<br> '
from (select distinct p_c_id, num_of_lights from dbo.spec_master order by num_of_lights) m2
where m.p_c_id = m2.p_c_id and num_of_lights is not null
for xml path(''), type).value('.[1]', 'nvarchar(max)'
) as numLights_spec
from dbo.spec_master m
inner join dbo.ProductVaration pv on pv.p_c_id = m.p_c_id
inner join dbo.Varation v on v.varation_id = pv.varation_type_id
where v.varation_id = 4
group by m.p_c_id
Personally, I'd just add the html tags in whatever back-end code is getting the result of the query.

How to get table-like query result on SQL Server 2005/8?

I have 3 tables:
users (id, name)
currency (id, name)
accounts (id, user_id, currency_id, amount)
And I want to read the data from accounts and present it in table-like view:
owner currency1 currency2 currency3
1 0 0 0
2 10 20 30
3 0 5 10
Where owner is ID of accounts.owner, currency1,2,3 - (SELECT id FROM currency WHERE name = '1',etc)
I can get such result only for one specific ID:
SELECT
SELECT amount FROM accounts WHERE currency = (SELECT id FROM currency WHERE name = 'currency1') AND owner = #user) AS [currency1],
SELECT amount FROM accounts WHERE currency = (SELECT id FROM currency WHERE name = 'currency2') AND owner = #user) AS [currency2],
SELECT amount FROM accounts WHERE currency = (SELECT id FROM currency WHERE name = 'currency2') AND owner = #user) AS [currency2]
Is it possible to get the same result for every object in users table? Without using Reporing Service, etc.
Use a pivot table and dynamic SQL to retrieve the columns
DECLARE #columns VARCHAR(2000)
SELECT #columns = STUFF(( SELECT DISTINCT TOP 100 PERCENT
'],[' + c.name
FROM currency AS c
ORDER BY '],[' + c.name
FOR XML PATH('')
), 1, 2, '') + ']'
DECLARE #query NVARCHAR(4000)
SET #query = N'SELECT UserName, ' + #columns +
'FROM
(SELECT u.Name AS UserName, c.name AS CurrencyName, a.Amount
FROM Accounts AS a WITH(NOLOCK)
JOIN Users u WITH(NOLOCK) ON a.user_id = u.user_id
JOIN Currency c WITH(NOLOCK) ON a.currency_id = c.currency_id
) p
PIVOT
(
SUM (p.Amount)
FOR p.CurrencyName IN
( '+ #columns +')
) AS pvt
ORDER BY UserName'
EXECUTE(#query)
This was tested in SQL Server 2005
Sounds like you want a Pivot table. It will be difficult to do if you have a varying number of rows in currency, but could still be done by using dynamiclly written sql.
Here's a resource from MSDN that explains how to use the pivot table: http://msdn.microsoft.com/en-us/library/ms177410.aspx
SELECT u.name, [1] AS Currency1, [2] AS Currency2, [3] AS Currency3
FROM
(SELECT u.Name AS UserName, c.Currency_ID, a.Amount
FROM Accounts AS a WITH(NOLOCK)
JOIN Users u WITH(NOLOCK) ON a.user_id = u.user_id
) p
PIVOT
(
SUM (p.Amount)
FOR p.Currency_id IN
( [1], [2], [3] )
) AS pvt
ORDER BY pvt.UserName