Updating multiple rows previous to a particular date - sql-server

I'm working with a website that had an update done to its business layer, so now I need to convert the old data to match the way new data is saved. I'm writing a SQL query that updates a couple of data columns on a member table, where the person_id matches on the member and registration code tables, an registration code is present on the reg cod table, and that reg code is flagged as used before a certain date on the reg code table.
UPDATE vs_member
SET premium_acct = 1, tenant_reg_key = (
SELECT DISTINCT tenant_reg_key
FROM vs_tenant_reg_key_tbl t
WHERE person_id = t.person_id)
WHERE person_id in (
SELECT t2.person_id
FROM vs_tenant_reg_key_tbl t2
WHERE person_id = t2.person_id AND t2.used = 1 AND premium_acct = 0 AND date_joined <= '2013-11-08')
I'm receiving an error stating the following: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Not exactly sure how to handle that, any help would be appreciated.

In your subselect, WHERE person_id = t.person_id probably isn't doing what you think.
Consider writing your UPDATE statement using joins instead of subselects. Perhaps something like this would do what you want.
UPDATE V
SET premium_acct = 1, tenant_reg_key = T.tenant_reg_key
FROM vs_member V
INNER JOIN vs_tenant_reg_key_tbl T ON T.person_id = V.person_id
WHERE T.used = 1 AND T.premium_acct = 0 AND T.date_joined < '2013-11-08'

Check if the following part of your query is returning more than one entry:
SELECT DISTINCT tenant_reg_key
FROM vs_tenant_reg_key_tbl t
WHERE person_id = t.person_id
If so, you won't be able to set tenant_reg_key to the results of this query, as it's essentially trying to add more than one value -- once, mind you -- to one entry.

Related

Update table from same table

I have a data set in which I would like to update a column PREVACCEPTID.
The update is based on the contents of the same table, a sample data is shown below:
The column should be updated after a search to see if station has had previous acceptances and what was this?
If we SELECT all DISTINCT 'ACCEPTID' for station A we would get the below.
I want to use this DISTINCT ACCEPTID to populate 'PREVACCEPTID'.
So whereever I have an entry with for e.g. '142692', I would lookup the sub-table and check if there are exists any previous ACCEPTID s, if that is the case populate with the previous one, in this case '142691' (see after results table as they are populated)
I have tried a few things now, I am getting an error for the below:
UPDATE a
SET a.PREVACCEPTID = (CASE
WHEN COUNT(DISTINCT b.ACCEPTID) = 1
THEN b.ACCEPTID
WHEN COUNT(DISTINCT b.ACCEPTID) > 1
AND b.ACCEPTID <> MIN(a.ACCEPTID)
THEN b.ACCEPTID - 1
END)
FROM dbo.table a
RIGHT JOIN dbo.table b ON b.STATION = a.STATION
AND b.PERIOD = a.PERIOD
AND b.ACCEPTID = a.ACCEPTID
I get this error:
Msg 157, Level 15, State 1, Line 326
An aggregate may not appear in the set list of an UPDATE statement.
The end result is per below:
I think a cte would be better option, but i have never used one.
Thanks in advance.
If I interpret your question and subsequent comments correctly, I assume you want the previous AcceptID to be populated to be last AcceptID for a given set of rows sharing the same Station and Period. Last I assume would be defined by the time components (StackDate and QTime). And, in the case where there is only one row for a given Station and Period, you'd want the Previous AcceptID to be set to be the same as AcceptID for that row.
Under the above conditions, below is a query that will work. Note: Replace table 'Test' with your own table name.
UPDATE t SET PrevAcceptID =
ISNULL(
(SELECT TOP 1 AcceptID
FROM Test t2
WHERE t2.Station = t.Station AND t2.Period = t.Period AND t2.AcceptID < t.AcceptID ORDER BY StackDate DESC, QTime DESC),
AcceptID)
FROM Test AS t

I receive multiple errors in SQL Server when trying to update a column in one table with a column for another

I have two tables dim_distributor and distributor_variant.
There is a distributorvariantname column in distributor_variant, and a distributorname column in dim_distributor that should contain identical values between the two tables.
Both tables have a distributorid column that should contain identical values between the two tables.
There are some distributorid fields that are set to 0 in the distributor_variant table, and I want to update them to the same distributorid values in the dim_distributor table.
There is also a distributorvariantid column in distributor_variant, and I do not want to update the one that is set to 0.
Below are the two queries I wrote to try to accomplish this.
The below query gives me a
The multi-part identifier "dv.DistributorID" could not be bound.
I checked spelling, what am I missing here?
update distributor_variant
set dv.distributorID = dd.distributorID
from distributor_variant dv
join dim_distributor dd on dd.distributorname = dv.distributorvariantname
where dv.distributorID =0 and dv.distributorVariantID !=0
The below query gives me
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I tried in before the parentheses and received an incorrect syntax before the keyword 'in' error.
update distributor_variant
set distributorID = (select dd.distributorID
from dim_distributor dd, distributor_variant dv
where dd.DistributorName = dv.distributorVariantName
and dv.distributorID =0 and dv.distributorVariantID !=0)
What am I doing wrong?
Any help would be much appreciated.
Updating with a join requires some weird syntax. You have to say update <alias> (no actual table name) before you've actually stated what that alias is actually tied to. Try this instead:
update dv
set dv.distributorID = dd.distributorID
from distributor_variant dv
join dim_distributor dd
on dd.distributorname = dv.distributorvariantname
where dv.distributorID =0 and dv.distributorVariantID !=0

Trying to Populate a Column with a Query

So I'm doing a data mining project for one of my classes. As part of it, I'm trying to apply Min Max Normalization to some of the data- which is the easy part. The hard part had been actually inserting the results of the queries into the table.
At first, I tried an INSERT INTO statement...
insert into dbo.CountsA([TotalCountMinMAx])
SELECT
1.00*(TotalCount-MinCount)/CountRange as TotalCountMinMax
FROM
(
SELECT
TotalCount,
MIN(TotalCount) OVER () AS MinCount,
MAX(TotalCount) OVER () - MIN(TotalCount) OVER () AS CountRange
FROM
dbo.CountsA
) X
The subquery itself works fine, but the moment I tried inserting the results into the table, it only inserted a number of null records. So instead of, say, updating ten entries in the TotalCountMinMAx column, it created ten additional records, and set all the columns to NULL.
After busting my head trying to figure that out, I tried using an UPDATE query instead.
update dbo.CountsA
set [TotalCountMinMAx]=(
SELECT
1.00*(TotalCount-MinCount)/CountRange as TotalCountMinMax
FROM
(
SELECT
TotalCount,
MIN(TotalCount) OVER () AS MinCount,
MAX(TotalCount) OVER () - MIN(TotalCount) OVER () AS CountRange
FROM
dbo.CountsA
) X)
This query failed to run entirely.
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
At this point, short of digging out my old SQL book and basically relearning SQL from scratch (I am very, very rusty), I'm out of ideas for making either of these codes work.
In case 1, when you insert, data will add row below old data. Example, if your table like:
ID | Col
1 2
2 4
After you insert just only Col column values: 3,4
Your table like this:
ID | Col
1 2
2 4
NULL 3
NULL 4
In case 2:
IF you use sub-query to insert like:
UPDATE Your_Table
SET Col = (<sub-query>)
sub-query must return a single value.
You can add where clause make sub-query return a single value, like this:
UPDATE Your_Table
SET Col = (SELECT ... FROM Your_Table) AS A
WHERE Col_ID = A.Col_ID
The problem is you are not correlating your sub-query that's the reason to get Sub-query retuned more than one row error.
Try using CTE to update which is easy and more readable.
;WITH cte
AS (SELECT 1.00 * ( TotalCount - MinCount ) / CountRange AS TotalCountMinMax_N,
TotalCountMinMax
FROM (SELECT TotalCount,
TotalCountMinMax,
Min(TotalCount)
OVER () AS MinCount,
Max(TotalCount)
OVER () - Min(TotalCount)
OVER () AS CountRange
FROM dbo.CountsA) X)
UPDATE cte
SET TotalCountMinMax = TotalCountMinMax_N

Calculation between table with multiple rows

I am encountering a problem of doing calculation between table in multiple rows.
This is my code:
UPDATE StockList
SET stkQuantity = stkQuantity - (SELECT quantity FROM mCalculate)
WHERE stkID = (SELECT stkID FROM mCalculate)
If table mCalculate has only one row of data, the calculation in StockList is successfully, but if table mCalculate has multiple rows of data, I get 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 anyone help me solve this problem and explain to me what's the problem I am having?
Image to refer:
Window:
Database:
You have to use join instead of sub query in this case
UPDATE S
SET stkQuantity = stkQuantity - M.quantity
From stocklist s
Join mcalculate m
On s.stkid = m.stkid
Among other issues, this line here:
WHERE stkID = (SELECT stkID FROM mCalculate)
The = needs a single value, so unless your mCalculate table has only 1 row you will be getting errors.
Your error of: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. is most likely due to the WHERE clause.
Your sub-select
(SELECT quantity FROM mCalculate)
Needs a WHERE clause that ensures this select returns only one row. Ditto for this:
(SELECT stkID FROM mCalculate)
Without the SCHEMA definitions for these tables, it's hard to help you figure out exactly what that WHERE clause should be.

JOIN ON subselect returns what I want, but surrounding select is missing records when subselect returns NULL

I have a table where I am storing records with a Created_On date and a Last_Updated_On date. Each new record will be written with a Created_On, and each subsequent update writes a new row with the same Created_On, but an updated Last_Updated_On.
I am trying to design a query to return the newest row of each. What I have looks something like this:
SELECT
t1.[id] as id,
t1.[Store_Number] as storeNumber,
t1.[Date_Of_Inventory] as dateOfInventory,
t1.[Created_On] as createdOn,
t1.[Last_Updated_On] as lastUpdatedOn
FROM [UserData].[dbo].[StoreResponses] t1
JOIN (
SELECT
[Store_Number],
[Date_Of_Inventory],
MAX([Created_On]) co,
MAX([Last_Updated_On]) luo
FROM [UserData].[dbo].[StoreResponses]
GROUP BY [Store_Number],[Date_Of_Inventory]) t2
ON
t1.[Store_Number] = t2.[Store_Number]
AND t1.[Created_On] = t2.co
AND t1.[Last_Updated_On] = t2.luo
AND t1.[Date_Of_Inventory] = t2.[Date_Of_Inventory]
WHERE t1.[Store_Number] = 123
ORDER BY t1.[Created_On] ASC
The subselect works fine...I see X number of rows, grouped by Store_Number and Date_Of_Inventory, some of which have luo (Last_Updated_On) values of NULL. However, those rows in the sub-select where luo is null do not appear in the overall results. In other words, where I get 6 results in the sub-select, I only get 2 in the overall results, and its only those rows where the Last_Updated_On is not NULL.
So, as a test, I wrote the following:
SELECT 1 WHERE NULL = NULL
And got no results, but, when I run:
SELECT 1 WHERE 1 = 1
I get back a result of 1. Its as if SQL Server is not relating NULL to NULL.
How can I fix this? Why wouldn't two fields compare when both values are NULL?
You could use Coalesce (example assuming Store_Number is an integer)
ON
Coalesce(t1.[Store_Number],0) = Coalesce(t2.[Store_Number],0)
The ANSI Null comparison is not enabled by default; NULL doesn't equal NULL.
You can enable this (if your business case and your Database design usage of NULL requires this) by the Hint:
SET ansi_nulls off
Another alternative basic turn around using:
ON ((t1.[Store_Number] = t2.[Store_Number]) OR
(t1.[Store_Number] IS NULL AND t2.[Store_Number] IS NULL))
Executing your POC:
SET ansi_nulls off
SELECT 1 WHERE NULL = NULL
Returns:
1
This also works:
AND EXISTS (SELECT t1.Store_Number INTERSECT SELECT t2.Store_Number)

Resources