Bad joinery: error when selecting from joins - sql

I am attempting to create an hourly dispatch report so for the "hourly" part (in SQL Server 2016) i tried to make queries for each hour and join them but i am getting errors that i cannot understand the query is like so:
Select
*
From
(SELECT
PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar) as '9 to 10'
from
[order] o
LEFT OUTER JOIN Order_LifeHistory h ON o.pkOrderID = h.fkOrderId
LEFT OUTER JOIN PackageGroups pg ON o.fkPackagingGroupId = pg.PackageCategoryID
Where
datepart(hour, dprocessedon) between 9
and 10
group by
PackageCategory
) as firstset
FULL JOIN (
SELECT
PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar) as '9 to 10'
from
[order] o
LEFT OUTER JOIN Order_LifeHistory h ON o.pkOrderID = h.fkOrderId
LEFT OUTER JOIN PackageGroups pg ON o.fkPackagingGroupId = pg.PackageCategoryID
Where
datepart(hour, dprocessedon) between 10
and 11
group by
PackageCategory
)as secondset on firstset.PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar) = secondset.PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar)
and I keep getting the following errors:
Invalid column name 'PackageCategory'.
Invalid column name 'UpdatedBy'.
Invalid column name 'PackageCategory'.
Invalid column name 'UpdatedBy'.
I cannot understand this as each query that i am joining works on its own.
am i missing something obvious?
please excuse my work a i'm very new at this and tend towards the Frankenstein method of writing queries (Digging up other peoples bits and pieces attach them together and hope for a metaphorical bolt of lightning)
thank you for reading

Because your firstset and secondset does not contain these columns.
They both contain only a single column called 9 to 10.
your full join's on clause should be firstset.[9 to 10] = secondset.[9 to 10]
Select
*
From
(SELECT
PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar) as '9 to 10'
from
[order] o
LEFT OUTER JOIN Order_LifeHistory h ON o.pkOrderID = h.fkOrderId
LEFT OUTER JOIN PackageGroups pg ON o.fkPackagingGroupId = pg.PackageCategoryID
Where
datepart(hour, dprocessedon) between 9
and 10
group by
PackageCategory
) as firstset
FULL JOIN (
SELECT
PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar) as '9 to 10'
from
[order] o
LEFT OUTER JOIN Order_LifeHistory h ON o.pkOrderID = h.fkOrderId
LEFT OUTER JOIN PackageGroups pg ON o.fkPackagingGroupId = pg.PackageCategoryID
Where
datepart(hour, dprocessedon) between 10
and 11
group by
PackageCategory
)as secondset on firstset.[9 to 10] = secondset.[9 to 10]

You're not selecting PackageCategory, you're selecting it's value plus other strings as a column named 9 to 10. Read it again thinking about it:
SELECT
PackageCategory + ' Count ' + Cast (Count (UpdatedBy) as varchar) as '9 to 10'
There are no columns named PackageCategory or UpdatedBy in your select.

Related

SQL JOIN IF EXISTS

I have a query using a JOIN to get some datas in others databases. But in a specific case, my entry will not have any data do do join.
So, it wont return nothing at all.
How can I ignore the join statement if not exists any compatible data?
Here is my SQL query:
SELECT
a.Id,
a.NomeCompleto,
a.CPF,
a.RelacaoFuncional,
a.Estabelecimento,
UPPER(LEFT(a.Cargo, 1)) + LOWER(SUBSTRING(a.Cargo, 2, LEN(a.Cargo))) as Cargo,
b.Unidade,
c.Departamento,
d.CentroCusto + ' - ' + Desc_CCUsto as CentroCusto,
a.UsuarioEspelho,
a.Observacao,
a.UsuarioRequerente,
a.Status,
CONVERT(NVARCHAR(10), a.Data, 103) AS Data,
a.AprovacaoInfra,
a.AprovacaoSistemas,
a.Usuario,
a.TipoSolicitacao
FROM
[SGW].[dbo].[TI01A] a
JOIN
[SGW].[dbo].[Unidade] b ON a.Id_Unidade = b.UnidadeID
JOIN
[SGW].[dbo].[Departamento] c ON a.Id_Departamento = c.DeptoID
JOIN
[HAZTEC_ORC].[dbo].[DimCentroCusto] d ON a.CentroCusto = d.CentroCusto
WHERE
a.Id = 6
You need to use
LEFT JOIN
Your query should be like below
SELECT a.Id,
a.NomeCompleto,
a.CPF,
a.RelacaoFuncional,
a.Estabelecimento,
UPPER(LEFT(a.Cargo, 1)) + LOWER(SUBSTRING(a.Cargo, 2, LEN(a.Cargo))) as Cargo,
b.Unidade,
c.Departamento,
d.CentroCusto + ' - ' + Desc_CCUsto as CentroCusto,
a.UsuarioEspelho,
a.Observacao,
a.UsuarioRequerente,
a.Status,
convert(nvarchar(10), a.Data, 103) as Data,
a.AprovacaoInfra,
a.AprovacaoSistemas,
a.Usuario,
a.TipoSolicitacao
FROM[SGW].[dbo].[TI01A] a
LEFT JOIN[SGW].[dbo].[Unidade] b on a.Id_Unidade = b.UnidadeID
LEFT JOIN[SGW].[dbo].[Departamento] c on a.Id_Departamento = c.DeptoID
LEFT JOIN[HAZTEC_ORC].[dbo].[DimCentroCusto] d on a.CentroCusto = d.CentroCusto
WHERE A.Id = 6

SQL get to select multiple names from select subquery

I am writing select statement in SQL Server. I have to add a select query.
select
acct.AccountID,
acct.Username,
acct.LastNm + ', ' + acct.FirstNm as Name ,
acct.Lastlogin,
acct.email as Email,
(select acct2.FirstNm + ' ' + acct2.LastNm as Name from tblUserAccount acct2
join tblReviewers ra2 on acct2.AccountID = ra2.ReviwerID) as Reviewers
from tblUserAccount acct
I need to get more names from a table called tblReviwers. So 1 user from the tblUserAccount table could be associated with multiple reviews.
The tblReviewers only has 3 column AnalystID, ReviewerID, and Date. When I select on the JOIN between TblUserAccount and TblReviewers on a test AccountID = AnalystID, I can get multiple ReviewerIDs, which their firstname and lastname are located in the tblUserAccount. This is the reason why I use a select subquery
When I run the query, I get the following error
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I am trying to write a VIEW to get a data.
Any help is greatly appreciated.
A query for a column name can only contain a single record result set. If you have an entry with multiple results causes that error.
I think you are missing disclosure of a possible extra component needed in the reviewers table, the who entered it. This will result in a query similar to the following.
The aliases and relations will appear obvious, but need to be confirmed for your actual structure.
select
EnterBy.AccountID,
EnterBy.Username,
EnterBy.LastNm + ', ' + EnterBy.FirstNm as Name ,
EnterBy.Lastlogin,
EnterBy.email as Email,
ReviewBy.FirstNm + ' ' + ReviewBy.LastNm as ReviewerName
from
tblReviewers r
tblUserAccount EnterBy
on r.AccountID = EnterBy.AccountID
tblUserAccount ReviewBy
on r.ReviwerID = ReviewBy.AccountID
REVISION BASED ON ADDITIONAL DATA
Based on providing the analystID on who entered, you should be good with
select
EnterBy.AccountID,
EnterBy.Username,
EnterBy.LastNm + ', ' + EnterBy.FirstNm as Name ,
EnterBy.Lastlogin,
EnterBy.email as Email,
STUFF(( Select
', [' + ReviewBy.LastNm + ', ' + ReviewBy.FirstNm + '] ' AS [text()]
From
tblReviewers r
JOIN tblUserAccount ReviewBy
on r.ReviwerID = ReviewBy.AccountID
where
r.AnaylstID = EnterBy.AccountID
For XML PATH('')), 1, 2, '' ) as AllReviewers
from
tblUserAccount EnterBy
You cannot have a column that contains multiple rows in a single result set, it just doesn't make sense from SQL perspective. Hence the error.
You should JOIN the tblReviewers table instead of subselecting it. That will yield all Reviewers. Then, JOIN again on the tblUserAccount table to get the name of the Reviewer, and you are all set.
SELECT
acct.AccountID,
acct.Username,
acct.LastNm + ', ' + acct.FirstNm as Name ,
acct.Lastlogin,
acct.email as Email,
acct2.LastNm + ', ' + acct2.FirstNm as ReviewerName ,
FROM tblUserAccount acct
JOIN tblReviewers revi
ON on acct.AccountID = revi.ReviewerID
JOIN tblUserAccount acct2
ON on acct2.AccountID = revi.AnalystID
Starting from Sql Server 2017, You can use something like STRING_AGG function, which combines values from multiple rows into a single string.
Then, your Reviewers column in your query might look like this:
(select STRING_AGG(Name, ',') from
(select acct2.FirstNm + ' ' + acct2.LastNm as Name from tblUserAccount acct2
join tblReviewers ra2 on acct2.AccountID = ra2.ReviwerID
where ra2.AnalystID = acct.AccountID)
) as Reviewers
In this case, names(first name + last name) of the reviewers for the current user will be separated by commas.
Subselects in select lists can only be used to return one value.
In your case, use joins
SELECT
a.AccountID,
a.Username,
a.LastNm + ', ' + a.FirstNm as Name ,
a.Lastlogin,
a.email as Email,
b.LastNm + ', ' + b.FirstNm as ReviewerName
FROM
tblUserAccount a
LEFT JOIN tblReviewers r ON a.AccountID = r.AnalystID
INNER JOIN tblUserAccount b ON r.ReviewerID = b.AccountID
I also used a LEFT JOIN to the reviewers table, in case there is no reviewer defined for an analyst.
You will get several rows per analyst, if more than one reviewer is assigned to it. Usually I solve this problem in the front-end by making a report that puts the main data in a group header (the analyst) and the related date (the reviewers) in the detail section of the report.
Starting with SQL Server 2017, you can also use the STRING_AGG function to concatenate the values of string expressions.
SELECT
a.AccountID,
a.Username,
a.LastNm + ', ' + a.FirstNm AS Name ,
a.Lastlogin,
a.email AS Email,
STRING_AGG(
( SELECT b.LastNm + ' ' + b.FirstNm
FROM
tblReviewers
INNER JOIN tblUserAccount b ON r.ReviewerID = b.AccountID
WHERE
r.AnalystID = a.AccountID ),
', ') AS ReviewerName
FROM
tblUserAccount a
This allows you to return more than one reviewer in one field.

SQL join on subquery with condition issue

I'm struggling when running a query on SQL. I need to strip the last 3 chars from a field that I have already created in my subquery and then join based upon that new field. The validation fails on line 5 "invalid column name 'PCD'."
SELECT
*, LEFT(SUBQUERY.PC,Len(SUBQUERY.PC) -3) AS PCD
FROM
(SELECT
PI.ClientPostcode, PI.casekey,
REPLACE( PI.ClientPostcode ,' ', '') As PC
FROM PI
WHERE LEN(PI.ClientPostcode) >= 5) AS SUBQUERY
INNER JOIN
[Postcodes] On outcode = PCD
Any help would be appreciated
You cant use the alias on the same level you defined.
SELECT *,
LEFT(SUBQUERY.pc, Len(SUBQUERY.pc) - 3) AS PCD
FROM (SELECT pi.clientpostcode,
pi.casekey,
Replace(pi.clientpostcode, ' ', '') AS PC
FROM pi
WHERE Len(pi.clientpostcode) >= 5) AS SUBQUERY
INNER JOIN [postcodes]
ON outcode = LEFT(SUBQUERY.pc, Len(SUBQUERY.pc) - 3)
^^^^ dont use the alias
Or you use it in a subquery like this
SELECT *
FROM (
SELECT *,
LEFT(SUBQUERY.pc, Len(SUBQUERY.pc) - 3) AS PCD
FROM (SELECT pi.clientpostcode,
pi.casekey,
Replace(pi.clientpostcode, ' ', '') AS PC
FROM pi
WHERE Len(pi.clientpostcode) >= 5) AS SUBQUERY
) other_subq
INNER JOIN [postcodes]
ON outcode = other_subq.PCD

SQL left join returns nothing when no matches

I am writing a stored procedure that adds the counts to two fields. I have the following code:
SELECT Distinct DateTime1,SUM(TICKETREQ1)SUMREQ, SUM(TicketPU1)SUMPU1, (count(*))AS GRADCOUNT
FROM TABLEA
WHERE YEAR = '2015'
AND TicketReq1 > 0
group by DateTime1
Select DISTINCT(DateTime2),SUM(TicketReq2) SUMREQ,SUM(TicketPU2)SUMPU2, (count(*))AS GRADCOUNT
from TABLEA
where TicketReq2 > 0
and YEAR = '2015'
Group by DateTime2;
SELECT Distinct c.DateTime1,SUM(c.TICKETREQ1 + b.TicketReq2)SUMREQ, SUM(c.TicketPU1 + b.TicketPU2)SUMPU1, (count(b.id) + count(c.id))AS GRADCOUNT
FROM TABLEA c
LEFT JOIN TABLEA b
ON (b.DateTime2 = c.DateTime1
AND b.TicketReq2 > 0
AND b.YEAR = '2015')
WHERE c.YEAR = '2015'
AND c.TicketReq1 > 0
group by c.DateTime1
This returns:
For some ceremonies the second query does bring in results and adds them correctly. But if there are no records then it fails.
How can I get it to join the two counts together (Query 1 and 2) so that Query 3 displays both counts even when there is no match
The problem is the SUM statements on query #3. b.TicketReq2 is null, therefore SUM(c.TICKETREQ1 + b.TicketReq2) should encounter an error. Try using ISNULL(b.TicketReq2, 0) in your SUM function calls.
Try full outer join instead of left join
SELECT Distinct c.CeremonyDateTime1,SUM(c.TICKETREQ1 + b.TicketReq2)SUMREQ, SUM(c.TicketPU1 + b.TicketPU2)SUMPU1, (count(b.gid) + count(c.gid))AS GRADCOUNT
FROM ComTicket c
FULL OUTER JOIN ComTicket b
ON (b.CeremonyDateTime2 = c.CeremonyDateTime1
AND b.TicketReq2 > 0
AND b.Gradterm = '201540')
WHERE c.gradterm = '201540'
AND c.TicketReq1 > 0
group by c.CeremonyDateTime1
It might helpful to you..

SQL show the max of count

I am using SQL server 2014. I have two tables Member and MemberPosition. The MemberPostion table records a history of each member in the database. The memberID is the primary key in the member table, and is a foreign key in the MemberPosition table. I need to return the member that has held the most positions.
Here is the query I am using:
Select
M.MemberFName + ' ' + M.MemberLName as Name
from Member M
Join MemberPosition MP
ON MP.MemberID = M.MemberID
Group By M.MemberFName + ' ' + M.MemberLName
Having Count(MP.MemberID) = (Select max(P) from
(Select Count(MP.MemberID) as P From MP))
I am getting an error near the last )
It tells me incorrect syntax near 'End of file'. Expecting AS,ID, or QUOTED_ID.
Can you tell me what I am doing wrong. I have tried following other examples from the forums but I cannot figure this out.
Subqueries in the from clause need an alias. In your case, this is buried deep in the having clause:
Select M.MemberFName + ' ' + M.MemberLName as Name
from Member M Join
MemberPosition MP
ON MP.MemberID = M.MemberID
Group By M.MemberFName + ' ' + M.MemberLName
Having Count(MP.MemberID) = (Select max(P)
from (Select Count(MP.MemberID) as P
From MP
) p
------------------------------------^
);
There are other ways to do what you want but this follows your query.
Here is an alternative:
Select TOP 1 WITH TIES M.MemberFName + ' ' + M.MemberLName as Name
from Member M Join
MemberPosition MP
ON MP.MemberID = M.MemberID
Group By M.MemberFName + ' ' + M.MemberLName
ORDER BY COUNT(*) DESC;