How to refer to the exact object - sql

I need a script that will change status to 0 for every student that has 3 or more absences
This is what I came up with:
UPDATE Group_cast
SET gc_Status = CASE WHEN ((SELECT COUNT(at_Presence)
FROM Attendance INNER JOIN Student ON at_stID = st_ID
INNER JOIN Group_cast ON st_ID = gc_stID
WHERE at_Presence = 0) >= 3) THEN 0
ELSE 1 END;
but it's updating every student status to 0 on the list and not just the one with 3 or more absences.

The problem is your subquery has a completely separate reference to Group_cast so it's counting a grand total for every Student, not just the one relevant to the row.
With no sample data, or expected results, this is impossible to test, but perhaps this?
UPDATE GC
SET gc_Status = CASE WHEN (SELECT COUNT(A.at_Presence) --Guessed the qualifier
FROM dbo.Attendance A
JOIN dbo.Student S ON A.at_stID = S.st_ID --Guessed the qualifiers
WHERE S.st_ID = GC.gc_stID --Guessed the qualifiers
AND A.at_Presence = 0) >= 3 THEN 0 --Guessed the qualifier
ELSE 1
END
FROM dbo.Group_cast GC;

Try this:
UPDATE Group_cast
set gc_Status =case when absentcnt>=3 then 0 end
from
(SELECT st_ID,COUNT(at_Presence) absentcnt
FROM Attendance INNER JOIN Student ON at_stID = st_ID
WHERE at_Presence = 0
group by st_ID)t where t.st_id=Group_cast.gc_stID

Related

Update Column in table using Select, Inner Join and Case When

I have a table called: Claim, where I've already moved data from another table called Damage. However, today I needed to add a column in Claim called ClaimStatusID. And to give values to ClaimStatusID I need to to it based on another column called DamageApprovedStatusID, which exists in yet another table called DamageErrand. Damage and DamageErrand has relation through a crosstable called DamageErrandCrossDamage. In that crosstable DamageErrandID and DamageID exists. Here, I've commented more information:
-- Claim has column ID which has the same ID as the table Damage
-- DamageErrand has DamageApprovedStatus ID which need to be inserted
-- to ClaimStatusID, where the ID's need to be correct.
-- Table Damage and Table DamageErrand has a cross table:
-- DamageErrandCrossDamage, where both of their ID's are stored
-- Claim.ID should therefore be the same as DamageErrandCrossDamage.DamageID
-- Since Claim.ID has the same ID as Damage.ID
-- IF DamageApprovedStatus = -1, SET ClaimStatusID = 0
-- IF DamageApprovedStatus = 0, SET ClaimStatusID = 4
-- IF DamageApprovedStatus = 1, SET ClaimStatusID = 2
And here's a SQL query I created for selecting and using Case When to give the correct statuses:
SELECT Claim.ID as claimid, DamageErrandID as damageerrandeid,
CASE --
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END AS DamageApprovedStatusID,
DamageApprovedStatusID
FROM
DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID =
DamageErrandCrossDamage.DamageErrandID
INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID
WHERE Claim.ID = DamageErrandCrossDamage.DamageID
I do believe this is correct, with the ID's matching and everything. But how can I actually update the table Claim with this? I know insert won't work since I have columns that does not allow null in Claim table. I tried doing something similar to:
--UPDATE Claim
--SET ClaimStatusID =
--(SELECT DamageApprovedStatusID FROM
--DamageErrand
--INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID =
-- DamageErrandCrossDamage.DamageErrandID
--INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID
--WHERE Claim.ID = DamageErrandCrossDamage.DamageID)
But obviously this won't work either. Really thankful for any help!
Btw: I'm using SQL-server for this.
I believe something like this should work:
UPDATE Claim
SET ClaimStatusID = alias.DamageApprovedStatusID
FROM (
SELECT DamageErrandCrossDamage.DamageID,
CASE
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END AS DamageApprovedStatusID
FROM DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID = DamageErrandCrossDamage.DamageErrandID
) alias
WHERE Claim.ID = alias.DamageID
I guess it could be rewritten like this too:
UPDATE Claim
SET ClaimStatusID = CASE
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END
FROM DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID = DamageErrandCrossDamage.DamageErrandID
INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID

SQL Server Select Statement Columns

Original Query:
select StudyID, count(CompletedDate), count(Removed), count(RemovalReason)
from Study a
full outer join Households b
on a.HouseholdID = b.HouseholdID
where StudyID = '123456'
and Removed = 1
and RemovalReason = 5
group by StudyID
How do I write out this query so that for each column (CompletedDate, Removed, and RemovalReason) is not restricted to the conditions (i.e. Removed = 1, Removal Reason = 5) and only applies to the specific column. If I execute this query, it will not show me the total count for CompletedDate because I'm restricting it to these conditions. Is there a way to write it directly next to count?
Table/Columns - Study:
HouseholdID (primary key),
StudyID,
CompletedDate
Table/Columns - Households:
HouseholdID (primary key),
Removed,
RemovalReason
I think you are looking for something like this, but your question is a little loose with details:
select StudyID
, count(CompletedDate)
, sum(case when Removed = 1 then 1 else 0 end)
, sum(case when RemovalReason = 5 then 1 else 0 end)
from Study a
join Households b
on a.HouseholdID = b.HouseholdID
where StudyID = '123456'
group by StudyID

How to sum a count of bookings to display total bookings for location and total value for location

I am writing a report that needs to show the number of bookings taken for a location with the total value of those bookings.
How do I sum the bookings column and show only one row for the location, that includes the columns set out in the example of expected data?
Select Statement Below:
SELECT
Locations.Description as LocationsDesc,
Locations.LocationGUID,
Venues.VenueName,
Venues.VenueGUID,
count (Bookings.BookingID) as Bookings,
Departments.DepartmentName,
Departments.DepartmentGUID,
sum(SalesTransactionDetails.NetDetailValue) as NetDetailValue,
sum(SalesTransactionDetails.DetailValue) as DetailValue,
SUM(CASE When Salestransactionlines.itemtype = 1 Then SalesTransactionDetails.NetDetailValue Else 0 End ) as RentalFee,
SUM(CASE When Salestransactionlines.itemtype = 2 Then SalesTransactionDetails.NetDetailValue Else 0 End ) as ExtraFee,
SalesTransactions.SalesTransactionGUID
FROM BookingLinesDetails
INNER JOIN Bookings ON BookingLinesDetails.BookingGUID=Bookings.BookingGUID
INNER JOIN Locations ON BookingLinesDetails.LocationGUID=Locations.LocationGUID
INNER JOIN Venues on Venues.Venueguid = Locations.Venueguid
INNER JOIN SalesTransactionDetails ON BookingLinesDetails.BookingLinesDetailGUID=SalesTransactionDetails.BookingLinesDetailGUID
INNER JOIN SalesTransactionLines ON SalesTransactionDetails.SalesTransactionLineGUID=SalesTransactionLines.SalesTransactionLineGUID
INNER JOIN SalesTransactions ON SalesTransactionLines.SalesTransactionGUID=SalesTransactions.SalesTransactionGUID
INNER JOIN Departments on Departments.DepartmentGUID = Locations.DepartmentGUID
WHERE
BookingLinesDetails.StartDateTime >= dbo.InzDateOnly(#pFromDate) and
BookingLinesDetails.StartDateTime < DateAdd(day,1,dbo.inzDateOnly(#pToDate)) and
Departments.DepartmentGUID in (Select GUID from dbo.InzSplitGUID(#DepartmentID)) and
(#IncludeAllLocationGroupsInVenues <> 0 or (#IncludeAllLocationGroupsInVenues = 0 )) and
Venues.VenueGUID in (Select GUID from dbo.InzSplitGUID(#VenueID)) and
salesTransactions.Status = 1 and -- remove cancelled
salestransactions.receiptonly = 0
GROUP BY
Locations.Description,
Locations.LocationGUID,
Venues.VenueName,
Venues.VenueGUID,
Departments.DepartmentName,
Departments.DepartmentGUID,
SalesTransactions.SalesTransactionGUID
The output is currently:
Desired output is:
LocationsDesc LocationGUID VenueGUID Bookings DepartmentName NetDetailValue DetailValue ExtraFee
Location - Deck Room 348A43F12 7DAD77BE 33 Aquatics Centre 2059.46 2162.5 0
I have attempted several versions of Count and sum. I believe I need to make the query a derived table and then select from that, but am not sure how to go about it, even if that is the answer.
Thank you in advance.

sql query updates all rows and not only where clause

I am having trouble executing this query:
update public.fortune_companies
set industry_id = (select id
from public.industries
where name = 'Agriculture, Forestry and Fishing')
from Temp_Sic_Fortune_Companies as temp
left join public.fortune_companies as fc on fc.account_name = temp.account_name
where temp.sic between '0' and '499';
I think this is supposed to set the industry_id for only ones that have a sic number of 0-499 but it actually sets every record to the same id. No matter if the sic number is between 0-499 or not.
Why is this.
DECLARE #id INT;
SELECT #id = id
FROM public.industries
WHERE name = 'Agriculture, Forestry and Fishing';
UPDATE fc
SET industry_id = #id
FROM public.fortune_companies AS fc
WHERE EXISTS
(
SELECT 1
FROM dbo.Temp_Sic_Fortune_Companies
WHERE account_name = fc.account_name
AND sic BETWEEN '0' and '499'
);
Of course, if temp.sic = '3000', it will be part of the set. This is one of the dangers of using the wrong data type (or the wrong operator). You can fix that by saying:
AND sic BETWEEN '0' and '499'
AND LEN(sic) <= 3
Or by saying:
AND CASE WHEN ISNUMERIC(sic) = 1 THEN
CONVERT(INT, sic) ELSE -1 END BETWEEN 0 AND 499
(This avoids errors if - since you've let them - someone enters a non-numeric value into the column.)
Or by using the right data type in the first place.
Change the left join to inner join

UDF not returning the same value as select contained in UDF

I created this UDF
CREATE FUNCTION [dbo].[HasExtendedRetentionSamples] (#BoxNumber varchar(20))
RETURNS int
AS
BEGIN
declare #cnt int
set #cnt = 0
select #cnt = (select count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate)
return #cnt
END
When I execute the UDF
select dbo.[HasExtendedRetentionSamples] ('ND011811001')
The value 0 is returned, which is incorrect,
When I execute the SQL statement contained in the UDF (replacing #BoxNumber with 'ND011811001')...
select count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
The value 5 is returned, which is correct.
So the big question is WHY????
All the datatype in the joins & case statement are the same.
I would change the function to this, take the count out of the subquery:
CREATE FUNCTION [dbo].[HasExtendedRetentionSamples] (#BoxNumber varchar(20))
RETURNS int
AS
BEGIN
declare #cnt int
set #cnt = 0
select #cnt = count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
return #cnt
END
try changing your CASE statement to:
case
when isnull([retention],0) = 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
I am embarrassed to say, I have found out why this was happening.....
When I created the table ExtendedRetentionSites, it was created & populated with me as the owner. I realized that and recreated the table with DBO as the owner, populating this table, but never dropping the table with the same name that I owned. I ran an insert statement & it inserted into ExtendedRetentionSites that I owned, but this data never made it to the table that DBO owned.
Soooooo when I ran the select script, it used ExtendedRetentionSites that I owned, that had the new row, that would give me the results I was looking for. When I ran the UDF, it used the table that DBO owned, without the new row thus returning nothing or a zero count.
Thanks to everyone who helped me out with this, I will now pull my head out of my ass & get back to work.
Thanks again to all!!!!