SQL update table by targeting unique row one int less - sql

What I have is a table with the following columns
All columns are nvarchar expect for the Date columns which are datetime
CreateDateA InvIDA StorageIDA CreateDateB InvIDB StorageIDB UniID
What I want to do is move the values on each row (based on UniID) into the represenative B columns where UniID is 1 less, so the 'A' columns where UniID = 2 should go to the B Columns where the UniID = 1.
This is the query i'm using but it's not updating any columns.
update InvSubmission
set CreateDateB = CreateDateA,
InvIDB = InvIDA ,
StorageIDB = StorageIDA
where StorageIDB = StorageIDA and UniID = (select UniID-1 from InvSubmission)
There is multiple storageid's in this table, however, each record has a match to at least one other row.

#PinnyM's answer is close, but in SQL Server, you have to name the updated table in the from clause also:
update toUpdate
set CreateDateB = sourceTable.CreateDateA,
InvIDB = sourceTable.InvIDA
FROM
InvSubmission toUpdate
inner Join
InvSubmission sourceTable
ON sourceTable.UniID = toUpdate.UniID + 1
AND sourceTable.StorageIDA = toUpdate.StorageIDB
Otherwise, this note becomes relevant:
If the object being updated is the same as the object in the FROM clause and there is only one reference to the object in the FROM clause, an object alias may or may not be specified
And then you're suffering the same problem that #Yuck pointed out - you're trying to compare the UniID value within a single row to a value one less than itself.

UniID = (select UniID-1 from InvSubmission) is equivalent to UniID = UniID - 1. So, for example, you're basically saying:
WHERE 2 = (2 - 1)
And that's never going to be true, which is why the query isn't modifying anything.
If both the A and B columns are in the same row you don't even need to qualify by using the ID clause. Otherwise you need to self-join like this:
update InvSubmission
set CreateDateB = B.CreateDateA,
InvIDB = B.InvIDA ,
StorageIDB = B.StorageIDA
from InvSubmission A INNER JOIN
InvSubmission B ON A.UniID = B.UniId - 1
where A.StorageIDB = A.StorageIDA;
As I mentioned it's a little confusing because your example makes it look like the columns are all contained in the same row...

It may actually depend on which RDBMS you are using (some are finicky on how aliases can be used), but you can try:
update InvSubmission
set CreateDateB = sourceTable.CreateDateA,
InvIDB = sourceTable.InvIDA ,
StorageIDB = sourceTable.StorageIDA
FROM InvSubmission sourceTable
WHERE sourceTable.UniID = InvSubmission.UniID + 1

Related

How to insert one column from a table into another based on a join/where clause

I have two tables, temp_am and amphibian. The relationship between the two tables comes from the lake_id and the survey_date column in both tables. Both tables have 24,109 entries.
temp_am
id
lake_id
survey_date
1
10,001
7/25/2001
5
10,005
7/27/2001
6
10,006
7/29/2001
etc...
amphibain
id
lake_id
survey_date
amhibian_survey_id
1
10,002
7/25/2001
2
10,005
7/27/2001
etc...
I want to input the temp_am.id into the amphibian.amphibian_survey_id when both lake_ids and survey dates equal each other.
I have tried this sql query but it never worked. I canceled the query after 600 seconds as I figured a 29,000 observation table should not take that long. Please let me know if you see any issues in my query statement.
update amphibian
set amphibian_survey_id = tm.id
from amphibian a
inner join temp_am tm
on a.lake_id = tm.lake_id
and a.survey_date = tm.survey_date
This query worked in microsoft access but not on DBeaver
UPDATE amphibian
inner JOIN amphibian_survey_meta_data md ON
(amphibian.survey_date = md.survey_date) AND (amphibian.lake_id = md.lake_id) SET amphibian.amphibian_survey_id = [md.id];
Postgres does not require repeating the table name for an update join. In this case even the join is not necessary just set <column> = ( select ... ) is sufficient. See demo here.
update amphibain a
set amhibian_survey_id =
( select tm.id
from temp_am tm
where (tm.lake_id, tm.survey_date) =
(a.lake_id, a.survey_date)
) ;

Self joining columns from the same table with calculation on one column not displaying column name

I am fairly new to SQL and having issues figuring out how to solve the simple issue below. I have a dataset I am trying to self-join, I am using (b.calendar_year_number -1) as one of the columns to join. I applied a calculation of -1 with the goal of trying to match values from the previous year. However, it is not working as the resulting column shows (No column name) with a screenshot attached below. How do I change the alias to b.calendar_year_number after the calculation?
Code:
SELECT a.day_within_fiscal_period,
a.calendar_month_name,
a.cost_period_rolling_three_month_start_date,
a.calendar_year_number,
b.day_within_fiscal_period,
b.calendar_month_name,
b.cost_period_rolling_three_month_start_date,
(b.calendar_year_number -1)
FROM [data_mart].[v_dim_date_consumer_complaints] AS a
JOIN [data_mart].[v_dim_date_consumer_complaints] AS b
ON b.day_within_fiscal_period = a.day_within_fiscal_period AND
b.calendar_month_name = a.calendar_month_name AND
b.calendar_year_number = a.calendar_year_number
I am using (b.calendar_year_number -1) as one of the columns to join.
Nope, you're not. Look at your join statement and you'll see the third condition is:
b.calendar_year_number = a.calendar_year_number
So just change that to include the calculation. As far as the 'no column name' issue, you can use colname = somelogic syntax or somelogic as colname. Below, I used the former syntax.
select a.day_within_fiscal_period,
a.calendar_month_name,
a.cost_period_rolling_three_month_start_date,
a.calendar_year_number,
b.day_within_fiscal_period,
b.calendar_month_name,
b.cost_period_rolling_three_month_start_date,
bCalYearNum = b.calendar_year_number
from [data_mart].[v_dim_date_consumer_complaints] a
left join [data_mart].[v_dim_date_consumer_complaints] b
on b.day_within_fiscal_period = a.day_within_fiscal_period
and b.calendar_month_name = a.calendar_month_name
and b.calendar_year_number - 1 = a.calendar_year_number;
You could use the analytical function LAG/LEAD to get your required result, no self-join necessary:
select a.day_within_fiscal_period,
a.calendar_month_name,
a.cost_period_rolling_three_month_start_date,
a.calendar_year_number,
old_cost_period_rolling_three_month_start_date =
LAG(cost_period_rolling_three_month_start_date) OVER
(PARTITION BY calendar_month_name, day_within_fiscal_period
ORDER BY calendar_year_number),
old_CalYearNum = LAG(calendar_year_number) OVER
(PARTITION BY calendar_month_name, day_within_fiscal_period
ORDER BY calendar_year_number)
from [data_mart].[v_dim_date_consumer_complaints] a

SQL Update row values from another row if value does not match

SQL rookie here. I'm trying to update a specific row of values using values from another row in the same table. However, I want the initial values to only update if it's null or does not match the new value.
My current unfinished script:
DECLARE #Record1 VARCHAR(50) = 'ID1',
#Record2 VARCHAR(50)='ID2'
UPDATE R1
SET r1.column1 = COALESCE(r1.column1, r2.column1),
r1.column2 = COALESCE(r1.column2, r2.column2),
r1.column3 = COALESCE(r1.column3, r2.column3),
r1.column4 = COALESCE(r1.column4, r2.column4)
FROM TABLE1 r1
INNER JOIN TABLE1 r2 ON r1.ID1 = #Record1 AND r2.ID2 = #Record2
I'm currently using SQL Server 2016 Management Studio.
EDIT:
After reading Sgeddes's reply, I realize my question was very dumb. Of course replacing everything in Record1 from Record2 makes the most sense.
I guess what I was fishing for was if there way a way to place a condition on each column to update. For example, if I wanted to update Record1's columns 1 & 2 only if NULL, but replace everything in columns 3 & 4 from Record2.
You would use a left join . . . carefully:
UPDATE R1
SET r1.column1 = coalesce(r1.column1, r2.column1),
r1.column2 = coalesce(r1.column2, r2.column2),
r1.column3 = coalesce(r1.column3, r2.column3),
r1.column4 = coalesce(r1.column4, r2.column4)
FROM TABLE1 r1 LEFT JOIN
TABLE1 r2
ON r2.ID2 = #Record2
WHERE r1.ID1 = #Record1 ;
Note that the condition on r1 goes in the where clause so it actually filters rows. The condition on t2 stays in the on clause, so all rows are returned, even when there are no matches in r2.

sql query is not working properly

i am trying to get non matching records from two table by comparing some columns which are common in both tables.i am using sql query to get the result. my first table is snd_marketvisits this table have properties like id ,pjpCode , section code, popCode .pop_name and landmark similary my 2nd table have pjpcode , section code, popcode popname are common and there are some other fields.i want to get the names of the pop which are not in second table but present in snd_marketvisit table by comparing popcode, sectioncode and pjpcode in both tables.
SELECT *
FROM snd_marketvisits sm
LEFT JOIN snd_marketvisit_pops sp ON
sm.distributorCode = sp.distributor AND
sm.pjpCode = sp.pjp AND
sm.sectionCode = sp.sectionCode AND
sm.popCode = sp.popCode
WHERE
sm.sectionCode = '00016' AND
sm.pjpCode = '0001' AND
sm.distributorCode = '00190A'
It depends on the database, as far as I know, but if you ask for NULL inside your yoined fields you should get only the rows without a match.
SELECT *
FROM snd_marketvisits sm
LEFT JOIN snd_marketvisit_pops sp ON
sm.distributorCode = sp.distributor AND
sm.pjpCode = sp.pjp AND
sm.sectionCode = sp.sectionCode AND
sm.popCode = sp.popCode
WHERE
sm.sectionCode = '00016' AND
sm.pjpCode = '0001' AND
sm.distributorCode = '00190A'
AND sp.distributor IS NULL

More than one row UPDATE

I need UPDATE some column. t1_id belongs table "h" and t2_id is column table "w". The picture shows the values equal to each other, but have different names, i.e. data of "18840263133600217"
= data of "339910"
How can I rename all t1_id to name from t2_id? I want to avoid the error "subquery in the expression returned more than one row"..
update h set h_user_id =
(select distinct w.h_user_id
from h inner join w
on h.h_ip = w.h_ip
where "some condition")
Can you use UPDATE FROM?
UPDATE h SET h_user_id = w.h_user_id
FROM w WHERE h.h_ip = w.h_ip AND "some condition"