Order by with UNION statement - sql-server

I have a little issue with the ORDER BY statement.
Here is my query (sorry I know is a little bit long, but I alredy cut a lot of the code)
(SELECT AssAttrezzi.ID, AssBombole.matricola, CONCAT(AssBombole.matricola, ' - ', Bombole.nome) AS Descrizione
FROM AssAttrezzi INNER JOIN
AssBombole
ON AssBombole.matricola = AssAttrezzi.attrezzoID INNER JOIN
Bombole
ON Bombole.ID = AssBombole.tipoBombolaID
WHERE AssAttrezzi.cantiereID=1
) UNION
(SELECT AssAttrezzi.ID, Saldatrici.matricola,CONCAT(Saldatrici.matricola, ' - ', Saldatrici.nome) AS Descrizione
FROM AssAttrezzi INNER JOIN
Saldatrici
ON Saldatrici.matricola = AssAttrezzi.attrezzoID
WHERE AssAttrezzi.cantiereID = 1
) UNION
(SELECT AssAttrezzi.ID, AssBanchiGlad.idAtrezzo, CONCAT(AssBanchiGlad.idAtrezzo, ' - ', BanchiGladiator.nome) AS Descrizione
FROM AssAttrezzi INNER JOIN
AssBanchiGlad
ON AssBanchiGlad.idAtrezzo = AssAttrezzi.attrezzoID INNER JOIN
BanchiGladiator
ON BanchiGladiator.ID = AssBanchiGlad.bancoID
WHERE AssAttrezzi.cantiereID = 1
) ORDER BY LEN(matricola), matricola
The problem is when I put ORDER BY at the end of each SELECT It gives me error:
Incorrect syntax near UNION
But when I try to put the ORDER BY at the end of all it gives me another error:
If the ORDER BY statement includes the UNION, INTERSECT or EXCEPT operator, the elements of the instruction must be specified in the selection list.
What? I would like to order by *.matricola basically matricola for me is the important one.

Try this:
(
SELECT AssAttrezzi.ID,
AssBombole.matricola,
CONCAT(AssBombole.matricola, ' - ', Bombole.nome) AS Descrizione,
LEN(AssBombole.matricola) AS matricola_len
FROM AssAttrezzi
INNER JOIN AssBombole ON AssBombole.matricola = AssAttrezzi.attrezzoID
INNER JOIN Bombole ON Bombole.ID = AssBombole.tipoBombolaID
WHERE AssAttrezzi.cantiereID=1
)
UNION
(
SELECT AssAttrezzi.ID,
Saldatrici.matricola,
CONCAT(Saldatrici.matricola, ' - ', Saldatrici.nome) AS Descrizione,
LEN(Saldatrici.matricola) AS matricola_len
FROM AssAttrezzi
INNER JOIN Saldatrici ON Saldatrici.matricola = AssAttrezzi.attrezzoID
WHERE AssAttrezzi.cantiereID = 1
)
UNION
(
SELECT AssAttrezzi.ID,
AssBanchiGlad.idAtrezzo,
CONCAT(AssBanchiGlad.idAtrezzo, ' - ', BanchiGladiator.nome) AS Descrizione,
LEN(AssBanchiGlad.idAtrezzo) AS matricola_len
FROM AssAttrezzi
INNER JOIN AssBanchiGlad ON AssBanchiGlad.idAtrezzo = AssAttrezzi.attrezzoID
INNER JOIN BanchiGladiator ON BanchiGladiator.ID = AssBanchiGlad.bancoID
WHERE AssAttrezzi.cantiereID = 1
)
ORDER BY LEN(matricola),
matricola

You can use custom sort :
SELECT . . . , 1 AS ID
UNION
SELECT . . . , 2
UNION
SELECT . . . , 3
ORDER BY ID;
You can't add separate order by clause when you use UNION/UNION ALL
EDIT :
SELECT AssAttrezzi.ID, AssBombole.matricola,
CONCAT(AssBombole.matricola, ' - ', Bombole.nome) AS Descrizione,
LEN(matricola) AS SortLen
FROM AssAttrezzi INNER JOIN
AssBombole
ON AssBombole.matricola = AssAttrezzi.attrezzoID INNER JOIN
Bombole
ON Bombole.ID = AssBombole.tipoBombolaID
WHERE AssAttrezzi.cantiereID = 1
UNION
SELECT AssAttrezzi.ID, Saldatrici.matricola,
CONCAT(Saldatrici.matricola, ' - ', Saldatrici.nome) AS Descrizione,
LEN(matricola)
FROM AssAttrezzi INNER JOIN
Saldatrici
ON Saldatrici.matricola = AssAttrezzi.attrezzoID
WHERE AssAttrezzi.cantiereID = 1
UNION
SELECT AssAttrezzi.ID, AssBanchiGlad.idAtrezzo,
CONCAT(AssBanchiGlad.idAtrezzo, ' - ', BanchiGladiator.nome) AS Descrizione,
LEN(matricola)
FROM AssAttrezzi INNER JOIN
AssBanchiGlad
ON AssBanchiGlad.idAtrezzo = AssAttrezzi.attrezzoID INNER JOIN
BanchiGladiator
ON BanchiGladiator.ID = AssBanchiGlad.bancoID
WHERE AssAttrezzi.cantiereID = 1
ORDER BY SortLen, matricola;

Related

Subquery and NOT NULL

I need some help with a subquery. My test column sometimes comes back NULL and if so I want to filter those out of my results set.
My stored procedure looks like this
SELECT
pl.Id AS Id,
pl.Name AS Name,
f.[Url] AS PrimaryImageUrl,
up.Id AS MemberId,
up.ProfessionalName,up.
AvatarUrl,
test = (SELECT
c.Id AS Id,
c.Name AS Name,
c.ContentImageUrl AS ImageUrl,
c.Price AS Price,
c.BPM AS BPM,
f.Id AS 'File.Id',
f.Url AS 'File.Name',
TotalCount = COUNT (c.Id) OVER()
FROM
dbo.Content c
INNER JOIN
dbo.PlayListContents pm ON c.Id = pm.ContentId
AND pm.PlaylistId = pl.Id
INNER JOIN
dbo.Files f ON c.ContentFileId = f.Id
FOR JSON PATH),
TotalCount = COUNT(1) OVER()
FROM
dbo.Playlist pl
INNER JOIN
dbo.UserProfiles up ON pl.UserId = up.UserId
INNER JOIN
[dbo].[Files] AS f ON pl.[PrimaryImageId] = f.[Id]
WHERE
(pl.Name LIKE '%' + #searchInput + '%')
AND test IS NOT NULL
Why is this last line, AND test IS NOT NULL invalid? I need my result set to have all results with test being NOT NULL
Try this
SELECT * FROM
(Select pl.Id as Id
,pl.Name as Name
,f.[Url] as PrimaryImageUrl
,up.Id as MemberId
,up.ProfessionalName
,up.AvatarUrl
,test = ( select c.Id as Id
,c.Name as Name
,c.ContentImageUrl as ImageUrl
,c.Price as Price
,c.BPM as BPM
,f.Id as 'File.Id'
,f.Url as 'File.Name'
,TotalCount = count(c.Id)Over()
from dbo.Content c
inner join dbo.PlayListContents pm on c.Id = pm.ContentId and pm.PlaylistId = pl.Id
inner join dbo.Files f on c.ContentFileId = f.Id
for json path)
--,TotalCount = COUNT(1) OVER()
from dbo.Playlist pl
inner join dbo.UserProfiles up on pl.UserId = up.UserId
inner join [dbo].[Files] as f ON pl.[PrimaryImageId] = f.[Id]
where ( pl.Name LIKE '%' + #searchInput + '%')) a
WHERE a.test IS NOT NULL
Columns in the SELECT are not available in the WHERE, due to SQL's logical order of operations.
Instead, place the value in CROSS APPLY, then filter after that:
SELECT
pl.Id AS Id,
pl.Name AS Name,
f.[Url] AS PrimaryImageUrl,
up.Id AS MemberId,
up.ProfessionalName,up.
AvatarUrl,
v.test,
TotalCount = COUNT(1) OVER()
FROM
dbo.Playlist pl
INNER JOIN
dbo.UserProfiles up ON pl.UserId = up.UserId
INNER JOIN
[dbo].[Files] AS f ON pl.[PrimaryImageId] = f.[Id]
CROSS APPLY (
SELECT test =
(SELECT
c.Id AS Id,
c.Name AS Name,
c.ContentImageUrl AS ImageUrl,
c.Price AS Price,
c.BPM AS BPM,
f.Id AS 'File.Id',
f.Url AS 'File.Name',
TotalCount = COUNT (c.Id) OVER()
FROM
dbo.Content c
INNER JOIN
dbo.PlayListContents pm ON c.Id = pm.ContentId
AND pm.PlaylistId = pl.Id
INNER JOIN
dbo.Files f ON c.ContentFileId = f.Id
FOR JSON PATH
)
) v
WHERE
(pl.Name LIKE '%' + #searchInput + '%')
AND v.test IS NOT NULL;

Using Left Join instead of Union

Currently I am using UNION statement to retrieve data from two tables. Can I use LEFT JOIN instead of UNION?
SELECT count(*), emp
FROM
(
SELECT *, name + '|' + age as emp
FROM Employee As E With(NoLock)
WHERE name = 'X'
And age In (1, 2)
AND active = 'Y'
UNION ALL
SELECT H.*, H.name + '|' + H.age AS emp
FROM Employee_History As H With(NoLock)
Inner Join Employee As E With(NoLock) On E.id = H.id
WHERE H.name = 'X'
And H.age In (1, 2)
And E.active != 'Y'
AND H.salary in
(
SELECT MAX(H2.salary)
From Employee_History As H2 With(NoLock)
group by H2.id
)
) AS A
GROUP BY A.emp
ORDER BY A.emp

SQL Pivot dynamic query error

I tried to convert rows values into columns...Below is my query...
Select * from (SELECT *
FROM ( SELECT PROJ.PROJ_ID,
PROJ.PROJ_NM AS [Project Name],
PROJ.PROJ_DS AS [Project Description],
convert(varchar(10), PROJ.PROJ_ACTL_LNCH_DT, 110) [Actual Completed Date],
PROJ.PROJ_SMRY_DS AS [Project Summary],
dbo.udf_BankContacts(PROJ.PROJ_ID) AS [BankContact],
convert(varchar(10), PROJ.PROJ_EST_LNCH_DT, 110) AS [Estimated Launch Date],
PROJ.ENTER_DT AS [Begin Date],
PROJ_STA.PROJ_STA_DS AS [Project Status],
SFTW_DEV_MTHD.SFTW_DEV_MTHD_NM AS [Software Development Method],
PROJ_PHASE.PROJ_PHASE_DS AS [Phase],
PROJ_CTGY.PROJ_CTGY_DS AS [Project Category],
(CASE WHEN PROJ.ARCH_IN='0' THEN 'N' ELSE 'C' END) AS [Archive],
PROJ.PHASE_CMNT_TX AS [Phase Comment],
PROD_TYPE_DS
FROM dbo.Project PROJ
left join dbo.PROJ_PROD PP on PROJ.PROJ_ID = PP.PROJ_ID
left join dbo.PROD_TYPE PT on PP.PROD_TYPE_ID = PT.PROD_TYPE_ID
LEFT JOIN DBO.PROJ_STA ON PROJ.PROJ_STA_ID = PROJ_STA.PROJ_STA_ID
left join dbo.SFTW_DEV_MTHD on PROJ.SFTW_DEV_MTHD_ID = SFTW_DEV_MTHD.SFTW_DEV_MTHD_ID
left join dbo.PROJ_PHASE on PROJ.PROJ_PHASE_ID = PROJ_PHASE.PROJ_PHASE_ID
left join dbo.PROJ_CTGY on PROJ.PROJ_CTGY_ID = PROJ_CTGY.PROJ_CTGY_ID
) data
PIVOT
( MAX(PROD_TYPE_DS)
FOR PROD_TYPE_DS IN ([PT1],[PT2])
) pvt2
where PROJ_ID is not null) AS ProdType
LEFT JOIN (SELECT *
FROM
(
select PROJ_ID,
PROJ_APRV_TYPE_DS = case
when col ='PROJ_APRV_TYPE_DS'
then PROJ_APRV_TYPE_DS
else PROJ_APRV_TYPE_DS+col end,
value
from
(
SELECT PROJ.PROJ_ID,
PAT.PROJ_APRV_TYPE_DS PROJ_APRV_TYPE_DS,
convert(varchar(10), PATS.APRV_EXPT_BY_DT, 120) APRV_EXPT_BY_DT,
convert(varchar(10), PATS.APRV_CMPL_DT, 120) APRV_CMPL_DT
FROM dbo.Project PROJ
left join [dbo].[PROJ_APRV_TYPE_STA] PATS
on PROJ.PROJ_ID = PATS.PROJ_ID
left join [dbo].[PROJ_APRV_STA] PAS
on PATS.PROJ_APRV_STA_ID = PAS.PROJ_APRV_STA_ID
right outer join dbo.PROJ_APRV_TYPE PAT
on PATS.PROJ_APRV_TYPE_ID = PAT.PROJ_APRV_TYPE_ID
) s
cross apply
(
select 'PROJ_APRV_TYPE_DS', PROJ_APRV_TYPE_DS union all
select ' Expected Date', APRV_EXPT_BY_DT union all
select ' Completed Date', APRV_CMPL_DT
) c (col, value)
) data
PIVOT
(
MAX(value)
FOR PROJ_APRV_TYPE_DS IN ([RMC Approval],[RMC Approval Expected Date],[RMC Approval Completed Date],[BOD Approval],[BOD Approval Expected Date],[BOD Approval Completed Date])
) pvt1 where PROJ_ID is not null ) AS Approval ON ProdType.PROJ_ID = Approval.PROJ_ID
LEFT JOIN (SELECT *
FROM ( SELECT PROJ.PROJ_ID,
ORG_SHRT_NM
FROM dbo.Project PROJ
left join dbo.PROJ_LGL_ENT_IMPCT PLEI on PROJ.PROJ_ID = PLEI.PROJ_ID
right outer join dbo.LGL_ENT LE on PLEI.LGL_ENT_ID = LE.LGL_ENT_ID
) data
PIVOT
( MAX(ORG_SHRT_NM)
FOR ORG_SHRT_NM IN ([AECB],[FSB],[TRS])
) pvt3
where PROJ_ID is not null) AS LegalEntity ON ProdType.PROJ_ID = LegalEntity.PROJ_ID LEFT JOIN
(;with cte as
(
SELECT PCGU.PROJ_ID,
name = u.USER_LST_NM + ', '+ u.USER_FIRST_NM,
CTC_GRP_DS
FROM dbo.[user] u
left join dbo.PROJ_CTC_GRP_USER PCGU
on u.USER_ID = PCGU.USER_ID
left join dbo.CTC_GRP CG
on PCGU.CTC_GRP_ID = CG.CTC_GRP_ID
)
select *
from
(
select c1.proj_id,
c1.CTC_GRP_DS,
STUFF(
(SELECT ', ' + c2.name
FROM cte c2
where c1.proj_id = c2.proj_id
and c1.CTC_GRP_DS = c2.CTC_GRP_DS
FOR XML PATH (''))
, 1, 1, '') AS name
from cte c1
) d
pivot
(
max(name)
for CTC_GRP_DS in ([Bank Contact],[Dept2])
) piv
where PROJ_ID is not null)
AS Dept ON ProdType.PROJ_ID = Dept.PROJ_ID
I am getting error
Msg 102, Level 15, State 1, Line 84
Incorrect syntax near ';'.
Msg 102, Level 15, State 1, Line 115
Incorrect syntax near ')'.
I am totally confused what i am missing it. I recently started pivot & dynamic query concepts...Please guide on it...
Your error is here.
(;with cte as
(
SELECT PCGU.PROJ_ID,
name = u.USER_LST_NM + ', '+ u.USER_FIRST_NM,
CTC_GRP_DS
FROM dbo.[user] u
left join dbo.PROJ_CTC_GRP_USER PCGU
on u.USER_ID = PCGU.USER_ID
left join dbo.CTC_GRP CG
on PCGU.CTC_GRP_ID = CG.CTC_GRP_ID
)
select *
from
(
select c1.proj_id,
c1.CTC_GRP_DS,
STUFF(
(SELECT ', ' + c2.name
FROM cte c2
where c1.proj_id = c2.proj_id
and c1.CTC_GRP_DS = c2.CTC_GRP_DS
FOR XML PATH (''))
, 1, 1, '') AS name
from cte c1
) d
You cannot have a CTE in sub selects like that.
You could try to put the CTE at the very top, or create a temp table for the select.
The error is with your CTE. You can't stick a CTE inside a query like that
(;with cte as

SQL- Subquery with aggregate functions (SQL Server)

My set up is as thus: I have three tables-
Students (StudentID, FirstName, LastName etc.),
StudentSemesters(StudentID,SemID etc.), and
Semesters(SemID, Year)
My requirement is to, get the details for each student but only for their last semester. Logically this implies the semester with the highest year number. I cannot seem to get the Query right. For simplicity 'Year' is just an integer (e.g. 2000, 1998). Below is the current query that I have been stuck at for some time:
SELECT dbo.Student.LastName + ' , ' + dbo.Student.FirstName AS Student, dbo.Student.Defence1Date, dbo.Student.Defence2Date, COUNT(StudentSemesters_1.SemID)
AS SemesterCount, dbo.Student.EntrySemester + ' - ' +
(SELECT dbo.StudentSemesters.SemID
FROM dbo.StudentSemesters INNER JOIN
dbo.ListSemesters ON dbo.StudentSemesters.SemID = dbo.ListSemesters.SemID
WHERE (dbo.Student.StudentCode = dbo.StudentSemesters.StudentCode)
GROUP BY dbo.StudentSemesters.SemID, dbo.ListSemesters.Year
HAVING (dbo.ListSemesters.Year = MAX(dbo.ListSemesters.Year))) AS Expr1
FROM dbo.Student INNER JOIN
dbo.StudentSemesters AS StudentSemesters_1 ON dbo.Student.StudentCode = StudentSemesters_1.StudentCode
GROUP BY dbo.Student.LastName, dbo.Student.FirstName, dbo.Student.Defence1Date, dbo.Student.Defence2Date, dbo.Student.EntrySemester,
dbo.Student.StudentCode
You can do this to get the details for only the last semester for each student:
SELECT
s.LastName + ' , ' + s.FirstName AS Student,
s.Defence1Date,
s.EntrySemester + ' - ' + s1.SemId AS Expr1
FROM dbo.Student AS s
INNER JOIN dbo.StudentSemesters AS S1 ON s.StudentCode = S1.StudentCode
INNER JOIN dbo.ListSemesters AS lm ON lm.SemID = s1.SemId
INNER JOIN
(
SELECT SemId, MAX(Year) AS MaxYear
FROM dbo.StudentSemesters
GROUP BY SemId
) AS s2 ON s2.semId = lm.SemId AND ls.Year = s2.MaxYear;
However, if you're using SQL Server 2005+, you can use the window function to do so:
WITH CTE
AS
(
SELECT
s.LastName + ' , ' + s.FirstName AS Student,
s.Defence1Date,
s.EntrySemester + ' - ' + s1.SemId AS Expr1,
ROW_NUMBER() OVER(PARTITION BY s1.SemId
ORDER BY Year DESC) AS RowNumber
FROM dbo.Student AS s
INNER JOIN dbo.StudentSemesters AS S1 ON s.StudentCode = S1.StudentCode
INNER JOIN dbo.ListSemesters AS lm ON lm.SemID = s1.SemId
)
SELECT
Student,
Defence1Date,
Expr1,
FROM CTE
WHERE RN = 1;
But this won't get the SemesterCount, but you might be able to make it like this (this is just a guess):
SELECT
s.LastName + ' , ' + s.FirstName AS Student,
s.Defence1Date,
s1.SemCount,
s.EntrySemester + ' - ' + s1.SemId AS Expr1
FROM dbo.Student AS s
INNER JOIN
(
SELECT StudentCode, COUNT(SemId) AS SemCount
FROM dbo.StudentSemesters
GROUP BY StudentCode
) AS S1 ON s.StudentCode = S1.StudentCode
INNER JOIN dbo.ListSemesters AS lm ON lm.SemID = s1.SemId
INNER JOIN
(
SELECT SemId, MAX(Year) AS MaxYear
FROM dbo.StudentSemesters
GROUP BY SemId
) AS s2 ON s2.semId = lm.SemId AND ls.Year = s2.MaxYear;

Sum of a value which is in the inner join

DECLARE #Names VARCHAR(8000)
select #Names = COALESCE(#Names + ', ', '') + (S.SubCategoryName+ '|' + CAST(R.RatingValue as varchar(5)))
from dbo.tblQuestions Q
inner join dbo.tblSubCategory S on Q.SubCategoryId=S.SubCategoryId
inner join dbo.tblRatings R on R.QuestionId=Q.QuestionId
inner join dbo.tblReviews RR ON R.ReviewId=RR.ReviewId
INNER JOIN dbo.tblCompanies C ON C.CompanyId=RR.CompanyId
where C.CompanyId=7
How do I sum the rating value?
Rating of what? Do you want to get sum of all rating values for specified company?
If so, try this:
select #Names = COALESCE(#Names + ', ', '') + (S.SubCategoryName+ '|' + CAST(R.RatingValue as varchar(5))),
SUM(R.RatingValue) as ratingSum
from dbo.tblQuestions Q
inner join dbo.tblSubCategory S on Q.SubCategoryId=S.SubCategoryId
inner join dbo.tblRatings R on R.QuestionId=Q.QuestionId
inner join dbo.tblReviews RR ON R.ReviewId=RR.ReviewId
INNER JOIN dbo.tblCompanies C ON C.CompanyId=RR.CompanyId
where C.CompanyId=7
group by C.CompanyId

Resources