Renumber keys in a table using sub-query - sql

I have a table that contains a list of deparments. The key ('code' in the sample) is just an assigned number. Unfortunately, this table now needs to accomodate some new software that comes with pre-defined deparment codes. Of course, these defined codes collide with the existing codes. I want to take the existing keys and increase each one by 200 to move them out of the collision space. I tried this query:
update [TEST-PH].[dbo].[Emp_PosDepartments]
set Code = (select code + 200 from [TEST-PH].[dbo].[Emp_PosDepartments] o where o.Code = Code)
But when I try to run this against SQL server, I get the following message:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Any suggestions how to accomplish the task of renumbering the keys?

The correct syntax doesn´t necessarily imply the use of a subquery:
update [TEST-PH].[dbo].[Emp_PosDepartments]
set Code = Code + 200

Related

Subquery returned more than 1 value - STIntersects

I have three tables
2x tables of observational point data with a point geom column (for different time periods)
A table of hexbins across the study area, with a polygon geom column
Both are in the same coordinate system.
The points tables are always intersecting the hexbin table. i.e. no points outside the hexbin layer.
Running the following query:
UPDATE OBS_MONDAY
SET GRID_ID = (
SELECT GRID_ID
FROM SYDHEX s with (index(FDO_Shape))
WHERE (OBS_MONDAY.Shape.STIntersects(s.Shape) = 1))
This executes fine, and calculates the GRID ID field from the Hexbin layer into a column in the Point layer.
However, running this same query against the 2nd point table causes 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.
Can someone help me pinpoint the problem here please.
You have to decide what to do. The "work-around" is to use SELECT TOP (1) or aggregation:
UPDATE OBS_MONDAY
SET GRID_ID = (SELECT TOP (1) GRID_ID
FROM SYDHEX s with (index(FDO_Shape))
WHERE OBS_MONDAY.Shape.STIntersects(s.Shape) = 1
);
By the way, this has nothing to do with spatial data. You are trying to assign a single value to GRID_ID and your subquery is returning more than one value.

Executing subquery to insert data on another table

I am getting this error while executing below query:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
This is the query I am using:
UPDATE BatchRecords SET Fees = (
SELECT
(Fees/NoOfPayments) as AvgTotal
FROM BatchFx
WHERE BatchRecords.BatchId = BatchFx.BatchId
AND BatchFx.CreatedOn < '2019-05-04'
);
Your error is happening because your WHERE clause is returning more than 1 record. So the update statement is confused which row does it need to update (because you most probably have more than 1 record per ID in the BatchFX table). I replicated your issue in this link and got the same output.
So to solve this issue you need to use an aggregator to group all the rows and output one record from the subquery.
UPDATE BatchRecords
SET Fees = (
SELECT
AVG(Fees / NoOfPayments) as AvgTotal
FROM BatchFx
WHERE BatchRecords.BatchId = BatchFx.BatchId
AND BatchFx.CreatedOn < '2019-05-04'
);
Hope this helps :)
The alias AvgTotal seems to imply that you want to take an average of something, so why not try doing that:
UPDATE BatchRecords br
SET Fees = (SELECT AVG(Fees/NoOfPayments) AS AvgTotal
FROM BatchFx bf
WHERE br.BatchId = bf.BatchId AND bf.CreatedOn < '2019-05-04');
Note that the error message you are seeing implies that the subquery in some cases would return more than one record. Selecting an aggregate function would be one way to get around this problem.

Named calculation subquery issue

I'm facing a little issue with SSAS, I'm trying to add a column to my fact table «Fact_Ventes» from a dimension table.
This is my query :
Select dc.[CuNumber]
from [Warehouse].[dbo].[Dim_Clients] dc
inner join [Warehouse].[dbo].[FACT_Ventes] fv on fv.SK_Clients = dc.SK_Clients
and this is the error I got:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Can any one help me on this?
I found the solution here : http://msdn.microsoft.com/en-us/library/ms174859.aspx and I wanna share it, it seems that my query need to be between brackets and I change the inner join to where clause , it works just fine :
(SELECT Dim_Clients.CuNumber
FROM Dim_Clients
where Dim_Clients.SK_Clients = FACT_Ventes.SK_Clients)
The Expression for a Named Calculation should return a Scalar Value. Yours would return a result set.
I would abandon the use of Named Calculations and Named Queries, and access all data via SQL views.
If I understand you correctly you're just trying to update your Fact_Ventes table with a value from another table. A simple UPDATE FROM should do the trick:
UPDATE [Warehouse].[dbo].[FACT_Ventes]
SET fv.CuNumber = dc.[CuNumber]
FROM [Warehouse].[dbo].[FACT_Ventes] fv
INNER JOIN [Warehouse].[dbo].[Dim_Clients] dc ON fv.SK_Clients = dc.SK_Clients
This assumes you've already updated your Fact_Ventes schema to include the new column.

Updating Variable with Current Row Value

I am trying to perform a complex operation where I pull the sum for an entire column of data and subtract the running subtotal from the sum for each row. I can do the component parts of Sum and Running Subtotal alone. Used this for running subtotal:
sum(UsageMetric) over(order by Nested1.IDNumber) as RunningTotal
However, I get this error when trying to comine them:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used
as an expression.
So I rigged this up, and it returns the 'stand-alone' running subtotal for a given row:
declare #TargetNumber BIGINT
Set #TargetNumber=(select Nested1.IDNumber from TargetTable Nested1 where Nested1.IdNumber='1234567890' and (Extraneous Criteria Here))
select sum(Usage.UsageMetric)
from Table_Usage Usage, IDTable IDT
where IDT.IDNumber <= #TargetNumber
and (Extraneous Criteria Here)
But what I would really like to do is be able to remove the qualifier "Nested1.IDNumber='1234567890' and just perform this for each IDNumber in TargetTable.
If I understand you correctly, you could do the following:
sum(UsageMetric) over () -
sum(UsageMetric) over (order by Nested1.IDNumber) as ...
Although simply reverting the order of rows in the OVER clause would yield the same results, I believe:
sum(UsageMetric) over (order by Nested1.IDNumber DESC) as ...

SQL Server 2008 UPDATE Statement WHERE clause precedence

I wrote the following query:
UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = IN_PNSN_ALL_TP_CNTRCT_CD + '3'
WHERE COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
AND CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
It checks to see if a field has a value in it and if it does it puts a 3 in a corresponding field if there isn't a 3 already in it. When I ran it, I got a string or binary data will be truncated error. The field is a VARCHAR(3) and there are rows in the table that already have 3 characters in them but the rows that I was actually doing the updating on via the WHERE filter had a MAX LEN of 2 so I was completely baffled as to why SQL Server was throwing me the truncation error. So I changed my UPDATE statement to:
UPDATE king_in
SET IN_PNSN_ALL_TP_CNTRCT_CD = k.IN_PNSN_ALL_TP_CNTRCT_CD + '3'
FROM king_in k
INNER JOIN
(
SELECT ki.row_key,
in_sqnc_nb
FROM king_in ki
INNER JOIN King_Ma km
ON ki.Row_Key = km.Row_Key
INNER JOIN King_Recs kr
ON km.doc_loc_nb = kr.ACK_ID
WHERE CHARINDEX('3', IN_PNSN_ALL_TP_CNTRCT_CD) = 0
AND COALESCE(IN_PNSN_ALL_TP_CNTRCT_TX, '') <> ''
) a
ON k.Row_Key = a.Row_Key
AND k.in_sqnc_nb = a.insr_sqnc_nb
and it works fine without error.
So it appears based on this that when doing an UPDATE statement without a FROM clause that SQL Server internally goes through and runs the SET statement before it filters the records based on the WHERE clause. Thats why I was getting the truncation error, because even though the records I wanted to update were less than 3 characters, there were rows in the table that had 3 characters in that field and when it couldn't add a '3' to the end of one of those rows, it threw the error.
So after all of that, I've got a handful of questions.
1) Why? Is there a specific DBMS reason that SQL Server wouldn't filter the result set before applying the SET statement?
2) Is this just a known thing about SQL that I never learned along the way?
3) Is there a setting in SQL Server to change this behavior?
Thanks in advance.
1 - Likely because your criteria are not SARGable - that is, they can't use an index. If the query optimizer determines it's faster to do a table scan, it'll go ahead and run on all the rows. This is especially likely when you filter on a function applied to the field like you do here.
2 - Yes. The optimizer will do what it thinks it best. You can get around this somewhat by using parentheses to force an evaluation order of your WHERE clause but in your example I don't think it would help since it forces a table scan regardless.
3 - No, you need to alter your data or your logic to allow indexes to be used. If you really really need to filter on existence of a certain character in a field, it probably should be it's own column and/or you should normalize that particular bit of data better.
A workaround for your particular instance would be to add a WHERE LEN(IN_PNSN_ALL_TP_CNTRCT_CD) < 3 as well.