Adding data to new column in table (insert into or update) - sql

What I try to achieve is to update all data, so the new data goes into Row_ID and all other columns.
I have a table created db.test
I added new column Row_ID(integer)
This ise the first Code for inserting data to table
Insert into db.test
(
STRING0 ,
CONTACT ,
STRING2 ,
TEMPLATE,
NAME ,
EXEC_ID,
SENDDATE,
OPENDATE,
CLICKDATE
)
SELECT
acc.STRING0 ,
a.CONTACT ,
acc.STRING2 ,
a.TEMPLATE ,
a.NAME ,
a.EXEC_ID,
a.SENDDATE,
A.OPENDATE,
A.CLICKDATE
FROM db.account acc
Join db.activity a
ON acc.object_id = a.rep_contact
left JOIN db.VAL v1
ON v1.row_id = a.CAMPAIGN_TYPE
AND (v1.OBJ_FIELD_ID in(850))
left JOIN db.VAL v2
ON v2.row_id = a.CAMPAIGN_TYPE
AND (v2.OBJ_FIELD_ID in(851))
The values for ROW_ID comes from table db.VAL, but do I use update like this
Update db.test
( row_id, -- This column as integer has greated
string0,
etc...)
Select
v1.row_Id,
acc.STRING0,
etc....
Ending is the same
I tried this kind of update query, but it didn't work.
What should I change?
Because I would prefer to just update table, not drop, create new, and all new data.
NB! SQL Server ( Sybase)

As data is already inserted in the table, now you will have to update
the values in new column row_id. Following pseudo code will work
just make sure the from clause fetches the correct value of v1.row_Id:
UPDATE db.test
SET row_id = v1.row_Id
FROM db.test t1
JOIN db.account acc ON acc.STRING0 = t1.STRING0
--all match columns will go here
AND acc.STRING2 = t1.STRING2
JOIN db.activity a ON acc.[object_id] = a.rep_contact
AND a.CONTACT = t1.CONTACT
AND a.TEMPLATE = t1.TEMPLATE
AND a.NAME = t1.NAME
AND a.EXEC_ID = t1.EXEC_ID
AND a.SENDDATE = t1.SENDDATE
AND A.OPENDATE = t1.OPENDATE
AND A.CLICKDATE = t1.CLICKDATE
LEFT JOIN db.VAL v1 ON v1.row_id = a.CAMPAIGN_TYPE
AND (v1.OBJ_FIELD_ID in(850))
LEFT JOIN db.VAL v2 ON v2.row_id = a.CAMPAIGN_TYPE
AND (v2.OBJ_FIELD_ID in(851))

Related

MERGE statement using OUTPUT with WHERE condition

I'm trying to insert data from one system into another so I keep an intermediate mapping table to keep the ids from old and new table.
I'm using a MERGE condition, is there any way to
DECLARE #TenantId INT = 1
MERGE dbo.[Account] AS t
USING (SELECT m.[AccountId],
m.[TenantId],
a.[ID_Account],
a.[Account_No],
a.[Account_Name],
FROM [Client1].dbo.[Account] a
LEFT JOIN migration.[Account] m ON m.[ID_Account] = a.[ID_Account] AND m.[TenantId] = #TenantId
) AS s
ON (t.[AccountId] = s.[AccountId] AND t.[TenantId] = s.[TenantId])
WHEN NOT MATCHED THEN
INSERT ([TenantId], [Number], [Name], [Active] )
VALUES (#TenantId, s.[Account_No], s.[Account_Name], 1)
OUTPUT #TenantId, inserted.[AccountId], s.[ID_Account] INTO migration.[Account];
This is fine, but if I try to run it a second time, the records are inserted again on my migration.[Account] table keeping repeated data. Is there any way to put a where condition on the output?
When you check to see if values from the source exist in the target, you check to see if the AccountId from migration.Account is equal to the AccountId from dbo.Account. You output the results to the migration table, but the original record still exists so it will be included in subsequent executions of the merge.
To fix your problem you need to either:
delete the original record
Add an isUpdated column in the migration table that you update after insertion and will prevent the source from being loaded.
Update the AccountId with the new AccountId so it will match the condition on subsequent executions.
Have the new record somehow cancel the original in the source record.
Here's a method with a new isUpdated and updates the accountId column:
UPDATE m SET
isUpdated = 1,
AccountId = o.NewAccountId
FROM migration.Account [m]
INNER JOIN (
MERGE dbo.[Account] AS t
USING (SELECT m.[AccountId],
m.[TenantId],
a.[ID_Account],
a.[Account_No],
a.[Account_Name],
FROM [Client1].dbo.[Account] a
LEFT JOIN migration.[Account] m ON m.[ID_Account] = a.[ID_Account]
AND m.[TenantId] = #TenantId
WHERE m.isUpdated IS NULL OR m.isUpdated = 0
) AS s
ON (t.[AccountId] = s.[AccountId] AND t.[TenantId] = s.[TenantId])
WHEN NOT MATCHED THEN
INSERT ([TenantId], [Number], [Name], [Active] )
VALUES (#TenantId, s.[Account_No], s.[Account_Name], 1)
OUTPUT #TenantId, s.AccountId [OriginalAccountId], inserted.[NewAccountId]
) [o] ON o.TenantId = m.TenantId AND o.OriginalAccountId = m.AccountId
What you want to do is do updates on when matched:
MERGE into dbo.[Account] AS destination
USING (SELECT m.[AccountId],
m.[TenantId],
a.[ID_Account],
a.[Account_No],
a.[Account_Name],
FROM [Client1].dbo.[Account] a
LEFT JOIN migration.[Account] m ON m.[ID_Account] = a.[ID_Account] AND m.[TenantId] = #TenantId
) AS holdinarea
ON (destination.[AccountId] = holdinarea.[AccountId] AND destination.[TenantId] = holdinarea.[TenantId])
WHEN MATCHED THEN
UPDATE set [AccountId]=holdinarea.accountid,
[TenantId]=holdinarea.tenantID
WHEN NOT MATCHED THEN
INSERT ([TenantId], [Number], [Name], [Active] )
VALUES (holdingarea.TenantId, holdingarea.[Account_No], holdingarea.[Account_Name], 1);

Only return value that matches the ID on table 1

I have tried all possible joins and sub-queries but I cant get the data to only return one value from table 2 that exactly matches the vendor ID. If I dont have the address included in the query, I get one hit for the vendor ID. How can I make it so that when I add the address, I only want the one vendor that I get prior to adding the address.
The vendor from table one must be VEN-CLASS IS NOT NULL.
This was my last attempt using subquery:
SELECT DISTINCT APVENMAST.VENDOR_GROUP,
APVENMAST.VENDOR,
APVENMAST.VENDOR_VNAME,
APVENMAST.VENDOR_CONTCT,
APVENMAST.TAX_ID,
Subquery.ADDR1
FROM (TEST.dbo.APVENMAST APVENMAST
INNER JOIN
(SELECT APVENADDR.ADDR1,
APVENADDR.VENDOR_GROUP,
APVENADDR.VENDOR,
APVENMAST.VEN_CLASS
FROM TEST.dbo.APVENADDR APVENADDR
INNER JOIN TEST.dbo.APVENMAST APVENMAST
ON (APVENADDR.VENDOR_GROUP = APVENMAST.VENDOR_GROUP)
AND (APVENADDR.VENDOR = APVENMAST.VENDOR)
WHERE (APVENMAST.VEN_CLASS IS NOT NULL)) Subquery
ON (APVENMAST.VENDOR_GROUP = Subquery.VENDOR_GROUP)
AND (APVENMAST.VENDOR = Subquery.VENDOR))
INNER JOIN TEST.dbo.APVENLOC APVENLOC
ON (APVENMAST.VENDOR_GROUP = APVENLOC.VENDOR_GROUP)
AND (APVENMAST.VENDOR = APVENLOC.VENDOR)
WHERE (APVENMAST.VEN_CLASS IS NOT NULL)
Try this:
SELECT APVENMAST.VENDOR_GROUP
, APVENMAST.VENDOR
, APVENMAST.VENDOR_VNAME
, APVENMAST.VENDOR_CONTCT
, APVENMAST.TAX_ID
, APVENADDR.ADDR1
FROM TEST.dbo.APVENMAST APVENMAST
INNER JOIN (
select VENDOR_GROUP, VENDOR, ADDR1
, row_number() over (partition by VENDOR_GROUP, VENDOR order by ADDR1) r
from TEST.dbo.APVENADDR
) APVENADDR
ON APVENADDR.VENDOR_GROUP = APVENMAST.VENDOR_GROUP
AND APVENADDR.VENDOR = APVENMAST.VENDOR
AND APVENADDR.r = 1
--do you need this table; you're not using it...
--INNER JOIN TEST.dbo.APVENLOC APVENLOC
--ON APVENMAST.VENDOR_GROUP = APVENLOC.VENDOR_GROUP
--AND APVENMAST.VENDOR = APVENLOC.VENDOR
WHERE APVENMAST.VEN_CLASS IS NOT NULL
--if the above inner join was to filter results, you can do this instead:
and exists (
select top 1 1
from TEST.dbo.APVENLOC APVENLOC
ON APVENMAST.VENDOR_GROUP = APVENLOC.VENDOR_GROUP
AND APVENMAST.VENDOR = APVENLOC.VENDOR
)
I found another column in the APVENLOC table that I can filter on to get the unique vendor. Turns out if the vendor address is for the main office, the vendor location is set blank.
Easier than I thought it would be!
SELECT DISTINCT APVENMAST.VENDOR_GROUP,
APVENMAST.VENDOR,
APVENMAST.VENDOR_VNAME,
APVENADDR.ADDR1,
APVENMAST.VENDOR_SNAME,
APVENADDR.LOCATION_CODE,
APVENMAST.VEN_CLASS
FROM TEST.dbo.APVENMAST APVENMAST
INNER JOIN TEST.dbo.APVENADDR APVENADDR
ON (APVENMAST.VENDOR_GROUP = APVENADDR.VENDOR_GROUP)
AND (APVENMAST.VENDOR = APVENADDR.VENDOR)
WHERE (APVENADDR.LOCATION_CODE = ' ')
Shaji

Why does a CTE in SQL Server execute the INNER JOIN when no conditions are met?

I have table mse that have all rows StatusId = 1. But in query like this INNER JOINED VIEW is executed regardless of value of column StatusId. How to prevent it?
WITH cte201401291517 AS
(
SELECT
'QuantityOutPerShift' = SUM([vsqo].[QuantityOutPerShift])
, [mse].[ShiftGroup]
, [mse].[Station]
, [vsqo].[Shift]
FROM
[dbo].[mse] AS mse
INNER JOIN
[dbo].[vmsqo] AS vsqo ON [mse].[Station] = [vsqo].[FromStation]
AND ( [mse].[ShiftGroup] = [vsqo].[ShiftGroup]
OR [mse].[ShiftGroup] = 'ALL') -- order is important!
WHERE
[mse].[StatusId] = 3
GROUP BY
[mse].[ShiftGroup]
, [mse].[Station]
, [vsqo].[Shift])
UPDATE
[dbo].[mse]
SET
[dbo].[mse].[QuantityOutPerShift] = [cte].[QuantityOutPerShift]
, [dbo].[mse].[ShiftCurrent] = [cte].[Shift]
--OUTPUT INSERTED.*
FROM
cte201401291517 AS cte
WHERE
[dbo].[mse].[Station] = [cte].[Station]
AND ( [dbo].[mse].[ShiftGroup] = [cte].[ShiftGroup]
OR [dbo].[mse].[ShiftGroup] = 'ALL' ) -- order is important!
AND [dbo].[mse].[StatusId] = 3;
I can't do this without CTE because of fact that I'm updating table with SUM that cannot be used in UPDATE statement.
I'm using SQL Server 2005

updating Table from Another Table with Criteria

i am trying to write a query that will update the schemeid of a row with the id of the matching row from another table.
tblschemes b holds the schemes detail and tblclaims_liberty a holds the claims data and the fields to join on are b.nett_scheme = a.schemename and a.agentcode = b.agentcode
why then id the query below allocating a schemeid to rows of data that do not match the agentcode??
update tblclaims_liberty
set tblclaims_liberty.schemeid = tblschemes.id
from tblschemes inner join tblclaims_liberty on tblclaims_liberty.schemename = tblschemes.nett_scheme and tblclaims_liberty.agentcode = tblschemes.agentcode
where
ce_report = 'yes'
and (tblclaims_liberty.schemeid != tblschemes.id or schemeid is null) --only updates rows that require updateing instead of 6mil+ lines of data.
can someone point me in the right direction?? why is it not recognising the agentcode match?
regards,
Adam
Try with this:
update tblclaims_liberty TLtoUpdate
set TLtoUpdate.schemeid =
(
select TS.id
from tblschemes TS inner join tblclaims_liberty TL on TL.schemename = TS.nett_scheme and TL.agentcode = TS.agentcode
where TL.schemeid = TLtoUpdate.schemeid
)
where TLtoUpdate.ce_report = 'yes' and TLtoUpdate.schemeid is null
Looks there was missing the TL.id condition in the subquery.

sql server update from select

Following the answer from this post, I have something like this:
update MyTable
set column1 = otherTable.SomeColumn,
column2 = otherTable.SomeOtherColumn
from MyTable
inner join
(select *some complex query here*) as otherTable
on MyTable.key_field = otherTable.key_field;
However, I keep getting this error:
The column prefix 'otherTable' does
not match with a table name or alias
name used in the query.
I'm not sure what's wrong. Can't I do such an update from a select query like this?
Any help would be greatly appreciated.
(I'm using *blush* sql server 2000.)
EDIT:
here's the actual query
update pdx_projects set pr_rpc_slr_amount_year_to_date = summary.SumSLR, pr_rpc_hours_year_to_date = summary.SumHours
from pdx_projects pr join (
select pr.pr_pk pr_pk, sum(tc.stc_slr_amount) SumSLR, sum(tc.stc_worked_hours) SumHours from pdx_time_and_cost_from_rpc tc
join pdx_rpc_projects sp on tc.stc_rpc_project_id = sp.sol_rpc_number
join pdx_rpc_links sl on sl.sol_fk = sp.sol_pk
join pdx_projects pr on pr_pk = sl.pr_fk
where tc.stc_time_card_year = year(getdate())
group by pr_pk
) as summary
on pr.pr_pk = summary.pr_pk
and the actual error message is
Server: Msg 107, Level 16, State 2,
Line 1 The column prefix 'summary'
does not match with a table name or
alias name used in the query.
I submit to you this altered query:
update x
set x.pr_rpc_slr_amount_year_to_date = summary.sumSLR,
x.pr_rpc_hours_year_to_date = summary.sumHours
from pdx_projects x
join (
select pr.pr_pk as pr_pk,
sum(tc.stc_slr_amount) as SumSLR,
sum(tc.stc_worked_hours) as SumHours
from pdx_time_and_cost_from_rpc tc
join pdx_rpc_projects sp on tc.stc_rpc_project_id = sp.sol_rpc_number
join pdx_rpc_links sl on sp.sol_pk = sl.sol_fk
join pdx_projects pr on sl.pr_fk = pr.pr_pk
where tc.stc_time_card_year = year(getdate())
group by pr.pr_pk
) as summary
on x.pr_pk = summary.pr_pk
Notably different here: I don't re-use the alias pr inside and outside of the complex query. I re-ordered the joins the way I like them (previously referenced table first,) and explicitly notated pr_pk in 2 places. I also changed the update syntax to use update <alias>.
Maybe not the answer you're looking for, but instead of generating hugely complex queries, I usually default to inserting the some complex query here into a table variable. Then you can do a simple update to MyTable with a join to the table variable. It may not be quite as efficient, but its much easier to maintain.
I couldn't replicate your error using SQL 2008 in 80 compatibility level. While this option doesn't guarantee that I'll get the same results as you, nothing appears to be out of place.
create table pdx_projects
(
pr_rpc_slr_amount_year_to_date varchar(max)
, pr_rpc_hours_year_to_date varchar(max)
, pr_pk varchar(max)
)
create table pdx_time_and_cost_from_rpc
(
stc_slr_amount decimal
, stc_worked_hours decimal
, stc_rpc_project_id varchar(max)
, stc_time_card_year varchar(max)
)
create table pdx_rpc_projects
(
sol_rpc_number varchar(max)
, sol_pk varchar(max)
)
create table pdx_rpc_links
(
sol_fk varchar(max)
, pr_fk varchar(max)
)
update pdx_projects
set
pr_rpc_slr_amount_year_to_date = summary.SumSLR
, pr_rpc_hours_year_to_date = summary.SumHours
from
pdx_projects pr
join (
select pr.pr_pk pr_pk
, sum(tc.stc_slr_amount) SumSLR
, sum(tc.stc_worked_hours) SumHours
from pdx_time_and_cost_from_rpc tc
join pdx_rpc_projects sp on tc.stc_rpc_project_id = sp.sol_rpc_number
join pdx_rpc_links sl on sl.sol_fk = sp.sol_pk
join pdx_projects pr on pr_pk = sl.pr_fk
where tc.stc_time_card_year = year(getdate())
group by pr_pk
) as summary
on pr.pr_pk = summary.pr_pk