SQL UPDATE 'The Column 'ID' was specified multiple times for 'a' - sql

I am fairly new to SQL and I'm having trouble finding out how to fix this error. I understand that I'll get the error because I'm pulling the same column name twice from the same table, so I've created different aliases for the tables.
What I am trying to do is update a table in my database using a query to pull data from a linked server.
Here is a sample:
UPDATE [Database].dbo.T1
SET
T1.Status = item.Status,
T1.CategoryA = c.DESC_TEXT,
T1.CategoryB = d.DESC_TEXT
FROM
(SELECT c.DESC_TEXT, d.DESC_TEXT
inner join CSM_CODE c ON c.DESC_CD = item.ParCat and c.DESC_TYPE = 'PARCAT'
inner join CSM_CODE d ON d.DESC_CD = item.ChCat and d.DESC_TYPE = 'CHCAT'
WHERE
T1.Status = 'NEW')) A
WHERE [Database].dbo.T1.ID = A.ID
Here is my exact error:
The column 'DESC_TEXT' was specified multiple times for 'A'
So I don't know what to do about the aliases in my subquery for this update. Any help is appreciated!

Thank you all for helping figure this out. I now know why I was still receiving errors. Once I created the alias within my sub query, I had failed to update that alias in the SET.
UPDATE [database].dbo.T1
SET
[STATUS] = A.[STATUS],
[Scrum Team] = A.team_name,
[Parent Category] = A.prodparcat,
[Child Category] = A.prodcat
FROM
(SELECT
item.SEQ_ID,
item.STATUS,
c.DESC_TEXT prodparcat,
d.DESC_TEXT prodcat
FROM item
inner join csm_code c ON c.DESC_CD = item.parent_cat_cd and c.DESC_TYPE = 'PRODPARCAT'
inner join CSM_CODE d ON d.DESC_CD = item.prod_cat and d.DESC_TYPE = 'PRODCAT'
WHERE
item.STATUS = 'NEW' ) A
WHERE
[database.dbo.T1.[external ID] = A.SEQ_ID
It's also important to note that I was querying a linked server which required some creativity with my alias. Overall a great learning experience.
Thanks again!

Instead of FROM it should be a update-join construct like below. Also use column alias name for the duplicated columns.
UPDATE [Database].dbo.T1
SET
T1.Status = item.Status,
T1.CategoryA = A.cdesk,
T1.CategoryB = A.ddesk
JOIN
(SELECT c.DESC_TEXT as cdesk, d.DESC_TEXT as ddesk
FROM item
inner join CSM_CODE c ON c.DESC_CD = item.ParCat and c.DESC_TYPE = 'PARCAT'
inner join CSM_CODE d ON d.DESC_CD = item.ChCat and d.DESC_TYPE = 'CHCAT'
WHERE T1.Status = 'NEW')) A
ON [Database].dbo.T1.ID = A.ID

You are combining a column named DESC_TEXT from two different tables into a single table, namely A in your case. In that case, you have to give these two columns different names, like DESC_TEXT_c and DESC_TEXT_d and update T1 accordingly.

I suspect you want:
UPDATE T1
SET Status = item.Status,
CategoryA = c.DESC_TEXT,
CategoryB = d.DESC_TEXT
FROM [Database].dbo.T1 T1 JOIN
CSM_CODE c
ON c.DESC_CD = T1.ParCat and c.DESC_TYPE = 'PARCAT' JOIN
CSM_CODE d
ON d.DESC_CD = item.ChCat and d.DESC_TYPE = 'CHCAT'
WHERE T1.Status = 'NEW';
As written, your code has multiple syntax errors. The two references to DESC_TEXT in the subquery are the tip of the iceberg. I believe the above is the logic you want.

You have specified DESC_TEST twice with
c.DESC_TEXT, d.DESC_TEXT
Try renaming to.
c.DESC_TEXT category_a , d.DESC_TEXT category_b
You'll also need an id in A to join on.
An example to give you an idea.
UPDATE [Database].dbo.T1
SET
T1.Status = A.Status,
T1.CategoryA = A.CategoryA,
T1.CategoryB = A.CategoryB
FROM
(SELECT item.status, c.id, c.DESC_TEXT CategoryA, d.DESC_TEXT CategoryB
from item -- added after seeing the answer.
inner join CSM_CODE c ON c.DESC_CD = item.ParCat and c.DESC_TYPE = 'PARCAT'
inner join CSM_CODE d ON d.DESC_CD = item.ChCat and d.DESC_TYPE = 'CHCAT'
WHERE
T1.Status = 'NEW')) A
WHERE [Database].dbo.T1.ID = A.ID
Untested

Related

Comparing values in two rows and getting ORA-00918: column ambiguously defined

I am trying to compare values from one column in two different rows using CASE statement. Inner SELECT statements are identical and working OK giving me fields that I need. Then I inner joined them on one of the key fields (KYCID). That's where I get "column ambiguously defined" error. I tried to remove duplicate rows by using DISTINCT - still the same error.
SELECT DISTINCT e.KYCID,
CASE WHEN e.HRAC_FLAG <> f.HRAC_FLAG THEN 'FALSE' ELSE 'TRUE' END AS FLAG_COMPARISON
FROM
(SELECT gt.task_id, gt.work_item_status, gt.work_item_type, gt.component_id, xref.HRAC_FLAG,
xref.case_nbr, xref.task_id, d.kycid, d.core_component_state
FROM kyc_gbl_main.global_task gt
inner join KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref on gt.component_id = xref.component_id
inner join kyc_rgn_nam_main.account a on xref.accountid = a.accountid
inner join kyc_rgn_nam_main.country_appx_account_xref b on a.accountid = b.accountid
inner join kyc_rgn_nam_main.country_appx c on c.cntry_appx_id = b.cntry_appx_id and
c.country_appx_state = b.country_appx_state
inner join kyc_rgn_nam_main.kyc_main d on d.kycid = c.kycid
where gt.work_item_type = 'HRAC_OVERLAY'
and gt.work_item_status = 'Completed') e
INNER JOIN
(select gt.task_id, gt.work_item_status, gt.work_item_type, gt.component_id, xref.HRAC_FLAG,
xref.case_nbr, xref.task_id, d.kycid, d.core_component_state
from kyc_gbl_main.global_task gt
inner join KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref on gt.component_id = xref.component_id
inner join kyc_rgn_nam_main.account a on xref.accountid = a.accountid
inner join kyc_rgn_nam_main.country_appx_account_xref b on a.accountid = b.accountid
inner join kyc_rgn_nam_main.country_appx c on c.cntry_appx_id = b.cntry_appx_id and
c.country_appx_state = b.country_appx_state
inner join kyc_rgn_nam_main.kyc_main d on d.kycid = c.kycid
where gt.work_item_type = 'HRAC_OVERLAY'
and gt.work_item_status = 'Completed') f
ON e.KYCID = f.KYCID
WHERE e.core_component_state ='ACTIVE'
AND f.core_component_state = 'IN_PROGRESS';
As determined with process of elimination, you reference the same named column in a SELECT query. To avoid this name collision, consider aliasing those particular columns.
Additionally, to avoid repetition, consider using a CTE via WITH and avoid using table aliases like (a, b, c) or (t1, t2, t3). Finally, move WHERE conditions to ON to filter before combining all data sources.
WITH sub AS (
SELECT gt.task_id AS gt_task_id -- RENAMED TO AVOID COLLISION
, gt.work_item_status
, gt.work_item_type
, gt.component_id
, xref.HRAC_FLAG
, xref.case_nbr
, xref.task_id AS x_ref_task_id -- RENAMED TO AVOID COLLISION
, k.kycid
, k.core_component_state
FROM kyc_gbl_main.global_task gt
INNER JOIN KYC_RGN_NAM_MAIN.CASE_HRAC_XREF xref
ON gt.component_id = xref.component_id
AND gt.work_item_type = 'HRAC_OVERLAY' -- MOVED FROM WHERE
AND gt.work_item_status = 'Completed' -- MOVED FROM WHERE
INNER JOIN kyc_rgn_nam_main.account acc
ON xref.accountid = acc.accountid
INNER JOIN kyc_rgn_nam_main.country_appx_account_xref cax
ON acc.accountid = cax.accountid
INNER JOIN kyc_rgn_nam_main.country_appx ca
ON ca.cntry_appx_id = cax.cntry_appx_id
AND ca.country_appx_state = cax.country_appx_state
INNER JOIN kyc_rgn_nam_main.kyc_main k
ON k.kycid = ca.kycid
)
SELECT DISTINCT
e.KYCID
, CASE
WHEN e.HRAC_FLAG <> f.HRAC_FLAG
THEN 'FALSE'
ELSE 'TRUE'
END AS FLAG_COMPARISON
FROM sub e
INNER JOIN sub f
ON e.KYCID = f.KYCID
AND e.core_component_state = 'ACTIVE' -- MOVED FROM WHERE
AND f.core_component_state = 'IN_PROGRESS' -- MOVED FROM WHERE

Multiple Join not working on two string attributes

I have the following issue:
I have several tables in my Database, in order to check for a specific criteria I have to join several tables, where I use the following statement:
SELECT *
FROM (SELECT * FROM (((((((((SELECT * FROM table1 WHERE tab1_id = 1) AS A
INNER JOIN (SELECT * FROM table2 WHERE tab2_variable IS NOT NULL) AS B
ON A.variable = B.variable)
INNER JOIN (SELECT table3.*, IIF(year='XXXX', 0, 1) AS flag FROM table3) AS C
ON A.h_name = C.h_name)
INNER JOIN (SELECT * FROM table4 WHERE s_flag = 0) AS D
ON C.v_type = D.v_type)
INNER JOIN table5
ON C.ng_type = table5.ng_type)
INNER JOIN table6
ON C.part = table6.part)
INNER JOIN table7
ON C.ifg = table7.ifg)
INNER JOIN table8
ON C.v_type = table8.v_type AND C.ng_typ = table8.ng_typ AND C.ntr_flag = table8.ntr_flag)
INNER JOIN table9
ON table8.ifg_sii_id = table9.ifg_sii_id)) AS F
LEFT JOIN table10
ON F.risk = table10.risk AND C.v_type = table10.v_type
AND F.series = table10.series
This statement fails. But when I remove one the following two join-conditions in the last Left JOIN, it works as intended:
F.risk = table10.risk and/or C.v_type = table10.v_type
They are both of type CHAR, whereas series is type TINYINT, I guess it has something to do with joining on multiple conditions with strings, but I'm not able to find a workaround, any ideas?
according to your current SQL, Table C is not visible as it's a sub query within F. instead of C.v_type you need to use F.c_v_type and the c_v_type field must come from C table like. select v_type as c_v_type from table3... as C
In the last part of your Query You could try to actually select the table and include the Where Clause Like so:
LEFT JOIN (Select * from table10 Where C.v_type = v_type AND F.series = series) as xx
ON F.risk = xx.risk
Hope this helps

JOIN syntax and order for multiple tables

SQL Gurus,
I have a query that uses the "old" style of join syntax as follows using 7 tables (table and column names changed to protect the innocent), as shown below:
SELECT v1_col, p1_col
FROM p1_tbl, p_tbl, p2_tbl, p3_tbl, v1_tbl, v2_tbl, v3_tbl
WHERE p1_code = 1
AND v1_code = 1
AND p1_date >= v1_date
AND p_uid = p1_uid
AND p2_uid = p1_uid AND p2_id = v2_id
AND p3_uid = p1_uid AND p3_id = v3_id
AND v2_uid = v1_uid
AND v3_uid = v1_uid
The query works just fine and produces the results it is supposed to, but as an academic exercise, I tried to rewrite the query using the more standard JOIN syntax, for example, below is one version I tried:
SELECT V1.v1_col, P1.p1_col
FROM p1_tbl P1, v1_tbl V1
JOIN p_tbl P ON ( P.p_uid = P1.p1_uid )
JOIN p2_tbl P2 ON ( P2.p2_uid = P1.p1_uid AND P2.p2_id = V2.v2_id )
JOIN p3_tbl P3 ON ( P3.p3_uid = P1.p1_uid AND P3.p3_id = V3.v3_id )
JOIN v2_tbl V2 ON ( V2.v2_uid = V1.v1_uid )
JOIN v3_tbl V3 ON ( V3.v3_uid = V1.v1_uid )
WHERE P1.p1_code = 1
AND V1.v1_code = 1
AND P1.p1_date >= V1.v1_date
But, no matter how I arrange the JOINs (using MS SQL 2008 R2), I keep running into the error:
The Multi-part identifier "col-name" could not be bound,
where "col-name" varies depending on the order of the JOINs I am attempting...
Does anyone have any good examples on how use the JOIN syntax with this number of tables??
Thanks in advance!
When you use JOIN-syntax you can only access columns from tables in your current join or previous joins. In fact it's easier to write the old syntax, but it's more error-prone, e.g. you can easily forget a join-condition.
This should be what you want.
SELECT v1_col, p1_col
FROM p1_tbl
JOIN v1_tbl ON p1_date >= v1_date
JOIN v2_tbl ON v2_uid = v1_uid
JOIN v3_tbl ON v3_uid = v1_uid
JOIN p_tbl ON p_uid = p1_uid
JOIN p2_tbl ON p2_uid = p1_uid AND p2_id = v2_id
JOIN p3_tbl ON p3_uid = p1_uid AND p3_id = v3_id
WHERE p1_code = 1
AND v1_code = 1
You are not naming the tables in your join such that it doesn't know which column is from which table. Try something like:
SELECT a.v1_col, b.p1_col
FROM p1_tbl b
JOIN p_tbl a ON b.p_uid = a.p1_uid
WHERE b.p1_code = 1
From your query above, I am assuming a naming convention of p2_uid comes from p2_tbl. Below id my best interpretation of WHERE joins to using INNER joins.
SELECT
v1_col, p1_col
FROM
p1_tbl
INNER JOIN p1_tbl
ON p1_tbl.p1_date >= v1_tbl.v1_date
INNER JOIN p_tbl
ON p_tbl.p_uid = p1_tbl.p1_uid
INNER JOIN p2_tbl
ON p2_tbl.p2_uid = p1_tbl.p1_uid
INNER JOIN v2_tbl
ON p2_tbl.p2_id = v2_tbl.v2_id
INNER JOIN p3_tbl
ON p3_tbl.p3_uid = p1_tbl.p1_uid
INNER JOIN v3_tbl
ON p3_tbl.p3_id = v3_tbl.v3_id
INNER JOIN v1_tbl
ON v1_tbl.v1_uid = v2_tbl.v2_uid
AND v1_tbl.v1_uid = v3_tbl.v2_uid
WHERE
p1_code = 1
AND
v1_code = 1
Some general points I have found useful in SQL statements with many joins.
Always fully qualify the names. I.e dont use ID , rahter use
TableName.ID
Dont use aliases unless there is meaning. (I.e. joining a table to
its self where aliasing is needed.)

I'm trying to update the data in table column "Supplier_Base.CreditBalance" with the sum of the colum "Purch" in table "Suppliers_Account"

This was what i'm trying but it does not work.
UPDATE
dbo.Supplier_Base SET dbo.Supplier_Base.CreditBalance (
SELECT
SUM(dbo.Suppliers_Account.Purch ) AS BAL,
FROM
dbo.Suppliers_Account
INNER JOIN
dbo.Supplier_Base ON dbo.Suppliers_Account.Code = dbo.Supplier_Base.Code
GROUP BY dbo.Suppliers_Account.Code, dbo.Supplier_Base.CreditBalance
HAVING (dbo.Suppliers_Account.Code = N'C003'))
Sub-queries aren't allowed in a SET statement. You can work around this by aliasing the tables and doing a JOIN instead.
Do you have a test environment where you can run queries with damaging production data? I think this is what you're looking for, but DO test it first:
UPDATE
b
SET
b.CreditBalance = SUM(a.Purch)
FROM
dbo.Suppliers_Account a
INNER JOIN
dbo.Supplier_Base b
ON
a.Code = b.Code
WHERE
a.Code = N'C003'
GROUP BY
a.Code
This is the correct syntax:
UPDATE SB
SET CreditBalance = SA.Purch
FROM dbo.Supplier_Base SB
INNER JOIN (SELECT Code, SUM(Purch) Purch
FROM dbo.Suppliers_Account)
GROUP BY Code) SA
ON SB.Code = SA.Code
WHERE SB.Code = N'C003'

SQL Server update with joins

I am trying to update a date in a table, based off of a MAX(date) in another table. To get the correct data to link up, I have to do 2 inner joins and 2 left outer joins.
I can select the correct data, it returns a Guid (PersonId) and the Date.
I have to use this information to update my original table. I am having trouble getting this to work, I still getting syntax errors.
update tblqualityassignments as assign
inner join tblrequirementteams as team on assign.guidmemberid = team.guidmemberid
set assign.dtmQAPCLed = dtmTaken
from
(
select reg.guidpersonid, max(certs.dtmTaken) as dtmTaken from tblqualityassignments as assign
inner join tblrequirementteams as team on assign.guidmemberid = team.guidmemberid
inner join tblregisteredusercerts as reg on team.guidpersonid = reg.guidpersonid
left outer join tblcerttaken as certs on certs.guidcertid = reg.guidcertid
left outer join tblCodesCertType as types on types.intcerttypeid = certs.intcerttypeid
where types.intcerttypeid = 1
and assign.guidmemberid = team.guidmemberid
group by reg.guidpersonid as data
)
where data.guidpersonid = team.guidpersonid
Assuming you are using SQL Server for this, then this should work:
UPDATE A
SET A.dtmQAPCLed = dtmTaken
FROM tblqualityassignments AS A
INNER JOIN tblrequirementteams as T
ON A.guidmemberid = T.guidmemberid
INNER JOIN (select reg.guidpersonid, max(certs.dtmTaken) as dtmTaken
from tblqualityassignments as assign
inner join tblrequirementteams as team
on assign.guidmemberid = team.guidmemberid
inner join tblregisteredusercerts as reg
on team.guidpersonid = reg.guidpersonid
left outer join tblcerttaken as certs
on certs.guidcertid = reg.guidcertid
left outer join tblCodesCertType as [types]
on [types].intcerttypeid = certs.intcerttypeid
where [types].intcerttypeid = 1
and assign.guidmemberid = team.guidmemberid
group by reg.guidpersonid) data
ON T.guidpersonid = data.guidpersonid