sql update using select and sub select with joins - sql

I have an update statement that I am using to change the value of my building field if certain criteria is met.
Here is where I tell it to set my building value to the result of my select statement
update Table set Building = (select case when child.date determined between child.entry date and child.withdrawal date
then child.building else child.[offender bldg]end
Then my select statement is then a product of another select statement where I have to define the value for date3 because it has nulls and I need it force it to be current date to ensure that I am capturing all the records that need to be updated.
from (select w.BUILDING, [Withdrawal Date] = case when WITHDRAWAL_DATE is null then GETDATE() else w.WITHDRAWAL_DATE end,a.DATE_DETERMINED,w.ENTRY_DATE,a.RESP_BUILDING,o.BUILDING[Offender Bldg]
from dbo._temp_disc_off a inner join dbo.offender o on (a.INCIDENT_ID = o.INCIDENT_ID) inner join dbo.entry w on (o.PERSON_ID = w.STUDENT_ID))child</b>
This next section is associated to the first select statement and filters for buildings that meet either criteria
where child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date] and child.RESP_BUILDING is null
or child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date] and child.RESP_BUILDING <> child.[Offender Bldg])</b>
I have to set it up this way, because I need to compare to a date and not a null value because my result set goes from 2425 to 461 if I don't set withdrawal date to getdate() if null.
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 know that it is trying to return multiple values, and that is what I want. But when I try to use IN instead of = I get an incorrect syntax error.
The statement is not being used in a stored procedure, I am just trying to mass update some records. Please help, and please over look the fact that my syntax is a little off.
Thanks in advance
Updated My Question with Full Block
*here is my full statement in one block, I made some changes to it since posting, but I am trying to do the same update the temp disc off action table resp_building field. I can only do this if the date_determined is between the entry and withdrawal dates, but in some cases the withdrawal date is null, so I add a sub select where I provide a value for withdrawal date.
update dbo._temp_disc_off_action
set RESP_BUILDING = (
select case when child.DATE_DETERMINED between child.entry_date and child.[Withdrawal Date]
then child.BUILDING else child.[Offender Bldg] end
from (
select w.BUILDING, [Withdrawal Date] = case when WITHDRAWAL_DATE is null
then GETDATE()
else w.WITHDRAWAL_DATE end,
a.DATE_DETERMINED, w.ENTRY_DATE, a.RESP_BUILDING, o.BUILDING [Offender Bldg]
from dbo._temp_disc_off_action a
inner join dbo.DISC_OFFENDER o
on a.INCIDENT_ID = o.INCIDENT_ID
inner join dbo.REG_ENTRY_WITH w
on o.PERSON_ID = w.STUDENT_ID
where w.BUILDING = 41) child
where child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date]
and child.RESP_BUILDING is null
or child.DATE_DETERMINED between child.ENTRY_DATE and child.[Withdrawal Date]
and child.RESP_BUILDING <> child.[Offender Bldg])

The problem is:
update Table set Building = (sub query).
What you are trying to do is update a single column, Building, with a single value returned from the sub query. However, your sub query is returning more than one value. So instead of Building 4, it gives you Building 4, 10, and 19. Sql Server can't set a single column to multiple values and throws the error.
The easiest way to debug is to convert your entire update statement into a select statement that selects the original value and the value you want to update to. You can examine the result select and see why you have duplicate rows from your sub select and figure out how to return a single value, or potentially concatenate or group multiple rows together to return a single value.

I figured it out, I was completely over complicating things and was able to update the fields I wanted by simply running a statement where I included CASE statement in my where clause. That allowed me check if the date determined is between the two dates, while replacing null values of my withdrawal date with current date. Here is my statement below:
UPDATE dbo._temp_disc_off_action SET RESP_BUILDING = w.BUILDING
FROM dbo._temp_disc_off_action a JOIN dbo.DISC_OFFENDER o ON (a.INCIDENT_ID = o.INCIDENT_ID) JOIN dbo.REG_ENTRY_WITH w ON (o.PERSON_ID = w.STUDENT_ID)
WHERE a.DATE_DETERMINED BETWEEN w.ENTRY_DATE AND CASE WHEN w.WITHDRAWAL_DATE IS NULL THEN GETDATE() ELSE w.WITHDRAWAL_DATE END AND a.RESP_BUILDING IS NULL AND **o.BUILDING = '41'
**OR a.DATE_DETERMINED BETWEEN w.ENTRY_DATE AND CASE WHEN ** w.WITHDRAWAL_DATE **IS NULL THEN GETDATE() ELSE w.WITHDRAWAL_DATE END
AND a.RESP_BUILDING <> o.BUILDING AND o.BUILDING = '41'

Related

Case Statement in SQL Query Issue

I'm trying to run a SQL query but an error happens when I run it.
Error:
[Code: -811, SQL State: 21000]
The result of a scalar fullselect, SELECT INTO statement, or VALUES INTO statement is more than one row..
SQLCODE=-811, SQLSTATE=21000, DRIVER=4.19.49
This is the SQL query that I am trying to run, I believe there is a problem with my CASE statement, I'm running out of solution. Please help, thanks a lot!
SELECT
ES.SHPMNT_REF,
(CASE
WHEN (ES.SERVICE_PROVIDER_NAME) IS NULL
THEN (SELECT BRDB.EXPORT_ONHAND.SERVICE_PROVIDER_NAME
FROM BRDB.EXPORT_ONHAND
WHERE BRDB.EXPORT_ONHAND.SHPMNT_REF = ES.SHPMNT_REF)
ELSE (ES.SERVICE_PROVIDER_NAME)
END) AS SP
FROM
BRDB.EXPORT_SHIPMENT ES
WHERE
ES.DATE_CREATE > CURRENT TIMESTAMP - 30 DAYS
I think this is what you are after. Joining on the table data you might need, then letting COALESCE check for null and get the other data if it is.
SELECT
ES.SHPMNT_REF,
COALESCE(ES.SERVICE_PROVIDER_NAME, OH.SERVICE_PROVIDER_NAME) AS SP
FROM BRDB.EXPORT_SHIPMENT ES
LEFT JOIN BRDB.EXPORT_ONHAND AS OH
ON ES.SHPMNT_REF = OH.SHPMNT_REF
WHERE
ES.DATE_CREATE > CURRENT TIMESTAMP - 30 DAYS
Maybe you should put inside the case:
THEN (SELECT TOP 1 BRDB.EXPORT_ONHAND.SERVICE_PROVIDER_NAME
The error is thrown because your subquery returns multiple values.
The best way would be joining the two table first and then get the value you need when the value is NULL.
That should work:
SELECT
ES.SHPMNT_REF
,CASE
WHEN ES.SERVICE_PROVIDER_NAME IS NULL
THEN EO.SERVICE_PROVIDER_NAME
ELSE ES.SERVICE_PROVIDER_NAME
END AS 'SP'
FROM BRDB.EXPORT_SHIPMENT ES
LEFT JOIN BRDB.EXPORT_ONHAND EO
ON ES.SHPMNT_REF = EO.SHPMNT_REF
WHERE ES.DATE_CREATE > CURRENT TIMESTAMP - 30 DAYS

Subquery returning multiple values ... not permitted to do so

declare #week1S DATE = '07/01/2016';
declare #week1E DATE = '07/07/2016';
WITH A as (
SELECT COUNT(ARB_accomplished) as ARB_accomplished_CNT
FROM arbimport
WHERE Requested_date between #week1S and #week1E AND arb_accomplished LIKE 'Y'
GROUP BY dispatch_group_name
)
Update ArbitrageResponse
Set arb_count1 = (SELECT ARB_accomplished_CNT FROM A)
I'm trying to update the column in one table based on a count of responses in another table. I'm trying to group on dispgroups and since my import table is massive I'm trying to filter it down to a selected date range. I'm going to have to run this a lot so It would be cool to keep the variables but not neccessary.
I want my response table to be recording responses every week so I just need columns being added to this table which is why I did an update.
I am getting an 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'm not sure if this has to do with my variables as they are being called in my subquery - I know that my subquery is returning the aggregated results of many different rows. Is there a better way to do this?
Try something like this:
set #countaccomplished = SELECT COUNT(ARB_accomplished) as ARB_accomplished_CNT
FROM arbimport
WHERE Requested_date between #week1S and #week1E AND arb_accomplished LIKE 'Y'
GROUP BY dispatch_group_name WHERE DISPATCH_GROUP_NAME = SOMETHING
Update ArbitrageResponse
Set arb_count1 = #countaccomplished
OR
WITH A as (
SELECT COUNT(ARB_accomplished) as ARB_accomplished_CNT, dispatch_group_name
FROM arbimport
WHERE Requested_date between #week1S and #week1E AND arb_accomplished LIKE 'Y'
GROUP BY dispatch_group_name
)
Update b
Set b.arb_count1 = a.ARB_accomplished_CNT
FROM ArbitrageResponse b where a.dispatch_group_name= b.dispatch_group_name
Without knowing the structure of your table, this is just a guess:
WITH A as (
SELECT dispatch_group_name, COUNT(ARB_accomplished) as ARB_accomplished_CNT
FROM arbimport
WHERE Requested_date between #week1S and #week1E AND arb_accomplished LIKE 'Y'
GROUP BY dispatch_group_name
)
UPDATE ar
SET arb_count1 = a.ARB_accomplished_CNT
FROM ArbitrageResponse ar JOIN
A
ON ar.dispatch_group_name = a.dispatch_group_name

Update column within CASE statement with results of a subquery postgres

I need to update a column based on the results of a subquery. If the subquery returns results for that column then the columns must be updated, is the query returns no results for that column then I need to update with 0.
I do not know where to place the subquery and how to combine it with the CASE statement. This is what I thought but the syntax is not correct. Can anybody help please?
(SELECT datazones.ogc_fid, count(*) as total
FROM suppliersnew suppliers, datazone_report_resupply datazones
WHERE St_contains(datazones.geom, suppliers.geometry) AND (suppliers.status = 'Under construction' OR
suppliers.status = 'Unknown' OR suppliers.status = 'Operational') GROUP by datazones.ogc_fid ORDER BY total ASC) sources
UPDATE datazone_report_resupply
SET es_actual =
CASE
WHEN datazone_report_resupply.ogc_fid = sources.ogc_fid THEN sources.total
ELSE 0
END
The query is a little hard to follow, because the aggregation is on the outer column (this is unusual). However, you don't need aggregation or order by. You only seem to care whether a row exists.
I think the logic is:
UPDATE datazone_report_resupply r
SET es_actual =
(CASE WHEN EXISTS (SELECT 1
FROM suppliersnew s
WHERE St_contains(r.geom, s.geometry) AND
s.status IN ('Under construction', 'Unknown', 'Operational')
)
THEN 1 ELSE 0
END);

How to add Order by in sql query

update Room set Status = case
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NULL
then 'U'
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NOT NULL
then 'A'
when Room.Status!='R' and Room.Status!='U' and Room.Status!='A'
then Room.Status
else 'R'
end
FROM Room JOIN Room_Rev
ON Room.Room_ID=Room_Rev.Room_ID
and
((Room_Rev.Start_Date >= '2015-03-22' and Room_Rev.End_Date <= '2015-03-22')
OR
(Room_Rev.Start_Date<= '2015-03-22' and Room_Rev.End_Date> '2015-03-22')
OR
(Room_Rev.Start_Date< '2015-03-22' and Room_Rev.End_Date>= '2015-03-22'))
How to add order by Rev_ID desc in the query?
There are two table which is Room and Room_Rev,
they are one to many relationship
The last two row ROM0006 already fill the In_DateTime and Out_DateTime,
thus it regard check out,
and the last row insert new reservation,
the In_DateTime is null
thus i need the query return 'R' (Reserved status)
As one of the possible solutions I suggest a nested query instead of a join in UPDATE statement. The logic of the update is not completely clear to me, so I leave the final update for OP to correct order of sorting (Note I used top 1 and order by room_ID in the nested SELECT statement). However, this approach allows to handle all usual techniques applicable for a SELECT.
update Room set Status = (select TOP 1 case
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NULL
then 'U'
when Room_Rev.In_DateTime IS NOT NULL and Room_Rev.Out_DateTime IS NOT NULL
then 'A'
when Room.Status!='R' and Room.Status!='U' and Room.Status!='A'
then Room.Status
else 'R'
end
FROM Room_Rev
WHERE Room.Room_ID=Room_Rev.Room_ID
and
((Room_Rev.Start_Date >= '2015-03-22' and Room_Rev.End_Date <= '2015-03-22')
OR
(Room_Rev.Start_Date<= '2015-03-22' and Room_Rev.End_Date> '2015-03-22')
OR
(Room_Rev.Start_Date< '2015-03-22' and Room_Rev.End_Date>= '2015-03-22'))
ORDER BY Room_Rev.Room_Id
)
PS. As a piece of advise I still assume that such approach is not valid. It prevents proper normalization of data. You'd rather have this information always queried dynamically when required, instead of writing static value to ROOM.status

SSRS Sql query with when clause and input parameter

I'm trying to get a SQL query working in SSRS.
This query is executed when I execute my report in SSRS. It is a select which simply populates my dataset.
I want to have the Date at the moment of the report execution on first execution and then I want the user to be able to input a different date if needed thus the need for the parameter.
Here it is :
Select contrat from contrats ctr,
INNER JOIN structure rs ON rs.id = ctr.id
INNER JOIN structure_members rsm ON rsm.id_structure = rs.id_structure
where
(((Date(ctr.date) = CASE WHEN ? IS NULL THEN Date(Now) END) or
(Date(rs.endDate) = CASE WHEN ? IS NULL THEN Date(Now) END)
GROUP BY crt.contrat
Don't mind any syntax error, I just simplified my query to get to the point : is this possible?
Can I do a case when end like this?
`CASE WHEN ? IS NULL THEN Date(Now)`
The ? is a date that I input such as 2014-08-04. The value could be null if I wanted to. That's why I'm trying to check if it is null then complete the query using Date(now) instead.
Thanks for your help.
Try this:
Select contrat from contrats ctr
INNER JOIN structure rs ON rs.id = ctr.id
INNER JOIN structure_members rsm ON rsm.id_structure = rs.id_structure
where
Date(ctr.date) = ISNULL(?,Today())
or
Date(rs.enddate) = ISNULL(?,Today())
GROUP BY crt.contrat
The CASE statement can be replaced by using ISNULL to get a default value for null input and using it in the comparison. If parameter is non-null, you compare the parameter value, else you compare today's date.