Acting on sql result row count - sql

I'm starting with this query:
SELECT TOP 1 Parties.FirstName + ' ' + Parties.MiddleName + ' ' + Parties.LastName AS Plaintiffs
FROM Jackets INNER JOIN
JacketPartyLinks ON Jackets.Id = JacketPartyLinks.Jacket_JacketPartyLink INNER JOIN
Parties ON Parties.Id = JacketPartyLinks.JacketPartyLink_Party
WHERE (Jackets.Id = #JacketID) AND (JacketPartyLinks.Role = 0)
What I'd like to accomplish is to take a count of what's returned, and if it's one row, do nothing. If it's more than one row, add something like ", et al". Notice that this query returns a single column, and it while it should be able to run standalone, it also needs to work as a subquery.
How can this be done?
EDIT: Add TOP 1

Use top and count..over and then wrap it in an outer query, like so:
select
Plantiffs + case when PlantiffCount > 1 then ', et al' else '' end as Plantiffs
from
(
SELECT TOP 1
Parties.FirstName + ' ' + Parties.MiddleName + ' ' + Parties.LastName as Plantiffs,
count(1) over () as PlantiffCount
FROM
Jackets
INNER JOIN JacketPartyLinks ON
Jackets.Id = JacketPartyLinks.Jacket_JacketPartyLink
INNER JOIN Parties ON
Parties.Id = JacketPartyLinks.JacketPartyLink_Party
WHERE
(Jackets.Id = #JacketID) AND (JacketPartyLinks.Role = 0)
order by Parties.LastName asc
) x
The over () part after count tells it to count all rows and not group by anything. This is why there isn't a group by clause in that query. You can use over with any aggregate function, which is pretty nifty.

Related

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.

Using the results of a SQL query as parameters for a second one

Our SQL developer put together the following query to basically pull a list of any employee who has logged into our system today. This query works perfectly and will spit out a list of names. What I need to do is take the list of names it spits out and then use those in a new query to change a column on a different table for each of those names.
select distinct(t.CC_FullName) as Employee,
t.CC_Supervisor as Supervisor,
t.StaffCimID
from (
select s.*,
r.CC_FullName,
r.CC_Supervisor,
r.StaffCimID
from (
select AgentFirstName + ' ' + AgentLastName as AgentName,
Agent
from pia.dbo.Five9IntraDayExtract with(nolock)
group by AgentFirstName + ' ' + AgentLastName,
Agent
) s
inner join pia.dbo.StaffInformationNew r with(nolock)
ON CASE
WHEN s.Agent LIKE '%_manual' AND s.Agent = r.Five9Name_MTM THEN 1
WHEN s.Agent NOT LIKE '%_manual' AND s.Agent = r.Five9Name THEN 1
ELSE 0
END = 1
and r.EndDate is null
) t
where t.CC_FullName is not null
and t.StaffCimID is not null
order by t.CC_FullName, t.CC_Supervisor
so basically after that runs I get a list with three columns. I need to take the name column and basically do the following:
Update Attendance Set Seated = '1' where name = 'John Doe'
I need to do that for every result from the initial query. What's the best way to do that?
Add that to the top of your query...
Update Attendance
Set Seated = '1'
where name in
(select t.CC_FullName from (
select s.*,
r.CC_FullName,
r.CC_Supervisor,
r.StaffCimID
from (
select AgentFirstName + ' ' + AgentLastName as AgentName,
Agent
from pia.dbo.Five9IntraDayExtract with(nolock)
group by AgentFirstName + ' ' + AgentLastName,
Agent
) s
inner join pia.dbo.StaffInformationNew r with(nolock)
ON CASE
WHEN s.Agent LIKE '%_manual' AND s.Agent = r.Five9Name_MTM THEN 1
WHEN s.Agent NOT LIKE '%_manual' AND s.Agent = r.Five9Name THEN 1
ELSE 0
END = 1
and r.EndDate is null
) t
where t.CC_FullName is not null
and t.StaffCimID is not null)

SQL LEFT OUTER JOIN with Count

I have this query here:
SELECT a.timeSlot, a.dateSlot, COUNT(concat(b.dateSlot, ' - ', b.timeSlot)) AS counter
FROM CP_VIP_Preview_TimeSlots as a
LEFT OUTER JOIN [CP-VIP-Preview] as b
ON a.timeSlot = b.dateSlot
AND a.dateSlot = b.timeSlot
GROUP BY a.timeSlot, a.dateSlot, a.[order]
ORDER BY a.[order]
What I am trying to do is get a count of each, which this query does, but something is messed up, any rows that have 0 appear as 1 and any row that actually has an items show the correct number, my problem if the row count is 0 its displaying 1....why is it doing that?
Your COUNT(concat(b.dateSlot, ' - ', b.timeSlot)) will always return at least one
Perhaps you can try
sum(IIF(b.dateSlot is null,0,1))
you need to use a HAVING for apply a filter after use group by, that way you do not count the records zero
SELECT a.timeSlot, a.dateSlot, COUNT(concat(b.dateSlot, ' - ', b.timeSlot)) AS counter
FROM CP_VIP_Preview_TimeSlots as a
LEFT OUTER JOIN [CP-VIP-Preview] as b
ON a.timeSlot = b.dateSlot
AND a.dateSlot = b.timeSlot
GROUP BY a.timeSlot, a.dateSlot, a.[order]
ORDER BY a.[order]
HAVING COUNT(concat(b.dateSlot, ' - ', b.timeSlot)) > 0

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..

sqlite query not getting all records if 1 table has missing data

I've got a very complex database with a lot of tables in SQLite. I'm trying to design a query that will report out a lot of data from those tables and also report out those sheep who may not have a record in one or more tables.
My query is:
SELECT sheep_table.sheep_id,
(SELECT tag_number FROM id_info_table WHERE official_id = "1" AND id_info_table.sheep_id = sheep_table.sheep_id AND (tag_date_off IS NULL or tag_date_off = '')) AS fedtag,
(SELECT tag_number FROM id_info_table WHERE tag_type = "4" AND id_info_table.sheep_id = sheep_table.sheep_id AND (tag_date_off IS NULL or tag_date_off = '')) AS farmtag,
(SELECT tag_number FROM id_info_table WHERE tag_type = "2" AND id_info_table.sheep_id = sheep_table.sheep_id AND (tag_date_off IS NULL or tag_date_off = '') and ( id_info_table.official_id is NULL or id_info_table.official_id = 0 )) AS eidtag,
sheep_table.sheep_name, codon171_table.codon171_alleles, sheep_ebv_table.usa_maternal_index, sheep_ebv_table.self_replacing_carcass_index, cluster_table.cluster_name, sheep_evaluation_table.id_evaluationid,
(sheep_table.birth_type +
sheep_table.codon171 +
sheep_evaluation_table.trait_score01 +
sheep_evaluation_table.trait_score02 +
sheep_evaluation_table.trait_score03 +
sheep_evaluation_table.trait_score04 +
sheep_evaluation_table.trait_score05 +
sheep_evaluation_table.trait_score06 +
sheep_evaluation_table.trait_score07 +
sheep_evaluation_table.trait_score08 +
sheep_evaluation_table.trait_score09 +
sheep_evaluation_table.trait_score10 +
(sheep_evaluation_table.trait_score11 / 10 )) as overall_score, sheep_evaluation_table.sheep_rank, sheep_evaluation_table.number_sheep_ranked,
sheep_table.alert01,
sheep_table.birth_date, sheep_sex_table.sex_abbrev, birth_type_table.birth_type,
sire_table.sheep_name as sire_name, dam_table.sheep_name as dam_name
FROM sheep_table
join codon171_table on sheep_table.codon171 = codon171_table.id_codon171id
join sheep_cluster_table on sheep_table.sheep_id = sheep_cluster_table.sheep_id
join cluster_table on cluster_table.id_clusternameid = sheep_cluster_table.which_cluster
join birth_type_table on sheep_table.birth_type = birth_type_table.id_birthtypeid
join sheep_sex_table on sheep_table.sex = sheep_sex_table.sex_sheepid
join sheep_table as sire_table on sheep_table.sire_id = sire_table.sheep_id
join sheep_table as dam_table on sheep_table.dam_id = dam_table.sheep_id
left outer join sheep_ebv_table on sheep_table.sheep_id = sheep_ebv_table.sheep_id
left outer join sheep_evaluation_table on sheep_table.sheep_id = sheep_evaluation_table.sheep_id
WHERE (sheep_table.remove_date IS NULL or sheep_table.remove_date is '' )
and (eval_date > "2014-10-03%" and eval_date < "2014-11%")
and sheep_ebv_table.ebv_date = "2014-11-01"
order by sheep_sex_table.sex_abbrev asc, cluster_name asc, self_replacing_carcass_index desc, usa_maternal_index desc, overall_score desc
If a given sheep does not have a record in the evaluation table or does not have a record in the EBV table no record is returned. I need all the current animals returned with all available data on them and just leave the fields for EBVs and evaluations null if they have no data.
I'm not understanding why I'm not getting them all since none of the sheep have all 3 ID types (federal, farm and EID) so there are nulls in those fields and I was expecting nulls in the evaluation sum and ebv fields as well.
Totally lost in what to do to fix it.
The problem would appear to be that you're using eval_date in the WHERE statement. I'm assuming that eval_date is in the sheep_evaluation_table, so when you use it in WHERE, it gets rid of any rows where eval_date is NULL, which it would be when you're using a LEFT OUTER JOIN and there's no matching record in sheep_evaluation_table.
Try putting the eval_date filter on the join instead, like this:
left outer join sheep_evaluation_table on sheep_table.sheep_id = sheep_evaluation_table.sheep_id
AND (eval_date > "2014-10-03%" and eval_date < "2014-11%")
WHERE (sheep_table.remove_date IS NULL or sheep_table.remove_date is '' )