UPDATE statement with JOIN in SQL Server Not Working as Expected - sql

I'm attempting to update the LAST_INSPECTION_FW field for all records in the VEHICLES_FW table with the last JOB_DATE_FW for records with the REASON_CODE_FW = 35. However, what's happening is that once the below code is executed, it's not taking into consideration the WHERE clause. This causes all of the records to update when it should just be updating those with the REASON_CODE_FW = 35.
Is there a way to restructure this code to get it working correctly? Please help, thanks!
UPDATE VEHICLES_FW
SET VEHICLES_FW.LAST_INSPECTION_FW = JOB_HEADERS_FW.FIELD2MAX
FROM VEHICLES_FW
INNER JOIN (SELECT VEHICLE_ID_FW, MAX(JOB_DATE_FW) AS FIELD2MAX
FROM JOB_HEADERS_FW
GROUP BY VEHICLE_ID_FW) AS JOB_HEADERS_FW
ON VEHICLES_FW.VEHICLE_ID_FW = JOB_HEADERS_FW.VEHICLE_ID_FW
INNER JOIN JOB_DETAILS_FW
ON JOB_NUMBER_FW = JOB_NUMBER_FW
WHERE REASON_CODE_FW = '35'

Common Table Expressions are your friend here. SQL Server's strange UPDATE ... FROM syntax is not. EG
with JOB_HEADERS_FW_BY_VEHICLE_ID as
(
SELECT VEHICLE_ID_FW, MAX(JOB_DATE_FW) AS FIELD2MAX
FROM JOB_HEADERS_FW
GROUP BY VEHICLE_ID_FW
), q as
(
Select VEHICLES_FW.LAST_INSPECTION_FW, JOB_HEADERS_FW_BY_VEHICLE_ID.FIELD2MAX NEW_LAST_INSPECTION_FW
FROM VEHICLES_FW
INNER JOIN JOB_HEADERS_FW_BY_VEHICLE_ID
ON VEHICLES_FW.VEHICLE_ID_FW = JOB_HEADERS_FW_BY_VEHICLE_ID.VEHICLE_ID_FW
INNER JOIN JOB_DETAILS_FW
ON JOB_NUMBER_FW = JOB_NUMBER_FW
WHERE REASON_CODE_FW = '35'
)
UPDATE q set LAST_INSPECTION_FW = NEW_LAST_INSPECTION_FW

I suspect this does what you want:
update v
set last_inspection_fw = (
select max(j.job_date_fw)
from job_headers_fw j
inner join job_details_fw jd on jd.job_number_fw = j.job_number_fw
where j.vehicle_id_fw = v.vehicle_id_fw and jd.reason_code_fw = 35
)
from vehicles_fw v

Related

ORA-00971: Missing SET keyword

I'm getting a confusing "ORA97100 missing SET keyword" error when trying to run this simple UPDATE statement.
UPDATE
(SELECT
RKAP_PROYEKSI.ID AS ID,
RKAP_PROYEKSI.TAHUN AS TAHUN,
RKAP_PROYEKSI.KODE_ANGGARAN AS KODE_ANGGARAN,
RKAP_PROYEKSI.JENIS_BIAYA AS JENIS_BIAYA,
RKAP_PROYEKSI.SUBTOTAL AS SUBTOTAL,
RKAP_PROYEKSI.TOTAL AS TOTAL,
RKAP_PROYEKSI.BELONGS_TO AS BELONGS_TO,
RKAP_PROYEKSI.NOMOR AS NOMOR,
RKAP_PROYEKSI.STATUS AS STATUS
FROM WOS.RKAP_PROYEKSI
LEFT JOIN WOS.RKAP_MASTER_KODE ON RKAP_MASTER_KODE.ID_KODE = RKAP_PROYEKSI.KODE_ANGGARAN
LEFT JOIN WOS.RKAP_USER ON RKAP_USER.BIRO = RKAP_MASTER_KODE.BIRO
WHERE TAHUN = '2018' AND RKAP_MASTER_KODE.BIRO = 'BSI') AS helper
SET helper.STATUS = 0
I've also tried to erase the "AS", but still get in error.
Any well thought to advise will be appreciated.
Thanks
You can use WITH..AS clause :
UPDATE RKAP_PROYEKSI R
SET STATUS = (
WITH RP AS
(
SELECT
RKAP_PROYEKSI.ID AS ID,
RKAP_PROYEKSI.TAHUN AS TAHUN,
RKAP_PROYEKSI.KODE_ANGGARAN AS KODE_ANGGARAN,
RKAP_PROYEKSI.JENIS_BIAYA AS JENIS_BIAYA,
RKAP_PROYEKSI.SUBTOTAL AS SUBTOTAL,
RKAP_PROYEKSI.TOTAL AS TOTAL,
RKAP_PROYEKSI.BELONGS_TO AS BELONGS_TO,
RKAP_PROYEKSI.NOMOR AS NOMOR,
RKAP_PROYEKSI.STATUS AS STATUS,
0 AS ZERO_STATUS
FROM WOS.RKAP_PROYEKSI
LEFT JOIN WOS.RKAP_MASTER_KODE ON RKAP_MASTER_KODE.ID_KODE = RKAP_PROYEKSI.KODE_ANGGARAN
LEFT JOIN WOS.RKAP_USER ON RKAP_USER.BIRO = RKAP_MASTER_KODE.BIRO
WHERE TAHUN = '2018' AND RKAP_MASTER_KODE.BIRO = 'BSI')
SELECT RP.ZERO_STATUS
FROM RP
WHERE RP.ID = R.ID
)
I think you can phrase this as:
UPDATE WOS.RKAP_PROYEKSI p
SET STATUS = 0
WHERE p.TAHUN = '2018' AND
EXISTS (SELECT 1
FROM WOS.RKAP_MASTER_KODE mk JOIN
WOS.RKAP_USER u
ON u.BIRO = mk.BIRO
WHERE mk.ID_KODE = p.KODE_ANGGARAN AND
mk.BIRO = 'BSI'
);
I don't see what RKAP_USER is being used for, but I left it in the query, just in case.

SQL error on UPDATE view with GROUP BY

This is the view
SELECT src.OfferAngebotsnummer AS OAngNr1,
SUM(src.Summe2) AS Summe,
CSDokument_1.OfferAngebotsnummer AS OAngNr2,
CSDokument_1.Auftragsvolumen
FROM (
SELECT OfferAngebotsnummer,
ROUND(Angebotssumme, 2) AS Summe2
FROM dbo.CSDokument
WHERE (MANeu = 'AS400') AND
(Art = '3') AND
(DokumentTyp = '3')) AS src
INNER JOIN
dbo.CSDokument AS CSDokument_1 ON
src.OfferAngebotsnummer = CSDokument_1.OfferAngebotsnummer
GROUP BY src.OfferAngebotsnummer,
CSDokument_1.OfferAngebotsnummer,
CSDokument_1.Auftragsvolumen
And this is the UPDATE statement
update UpdateAuftragsvolumenAngebot
set Auftragsvolumen = Summe
where Auftragsvolumen <> Summe
But I get an error that it's not allowed to use UPDATE on view with group by clause.
Cannot update the view or function 'UpdateAuftragsvolumenAngebot'
because it contains aggregates, or a DISTINCT or GROUP BY clause,
or PIVOT or UNPIVOT operator.
How can I accomplish the UPDATE?
I would suggest not using the view and just move it into a correlated sub-query like the below. I suggest that because as soon as you aggregate a view you cannot update the underlying tables.
update CSDokument
set Auftragsvolumen = Summe
from CSDokument
inner join
(
SELECT OfferAngebotsnummer,
ROUND(Angebotssumme, 2) AS Summe2
FROM dbo.CSDokument
WHERE (MANeu = 'AS400') AND
(Art = '3') AND
(DokumentTyp = '3')) AS src
INNER JOIN
dbo.CSDokument AS CSDokument_1 ON
src.OfferAngebotsnummer = CSDokument_1.OfferAngebotsnummer
GROUP BY src.OfferAngebotsnummer,
CSDokument_1.OfferAngebotsnummer,
CSDokument_1.Auftragsvolumen
) as s
on s.OfferAngebotsnummer = CSDokument.OfferAngebotsnummer
where CSDokument.Auftragsvolumen <> s.Summe
I believe you should use the group by in your sub-query and not at the join stage.

update with subquery

The code :
UPDATE tt_t_documents
SET t_Doc_header_ID = (SELECT
MIN(dh.Doc_header_ID)
FROM tt_t_documents td WITH (NOLOCK)
JOIN Doc_header dh WITH (NOLOCK)
ON dh.DH_doc_number = td.t_dh_doc_number
AND dh.DH_sub = 1
JOIN Pred_entry pe WITH (NOLOCK)
ON pe.Pred_entry_ID = dh.DH_pred_entry
JOIN Doc_type dt WITH (NOLOCK)
ON dty.Doc_type_ID = pe.PD_doc_type
AND dt.DT_mode = 5
HAVING COUNT(dh.Doc_header_ID) = 1);
I want to update my columns, but before that I also want to check if there is only one ID found.
The problem in this select is that I get more than one ID.
How can I write a query that updates each row and checks in the same query that there is only one id found?
I am guessing that you intend something like this:
update td
set t_Doc_header_ID = min_Doc_header_ID
from tt_t_documents td join
(select DH_doc_number, min(dh.Doc_header_ID) as min_Doc_header_ID
from Doc_header dh join
Pred_entry pe
on pe.Pred_entry_ID = dh.DH_pred_entry join
Doc_type dt
on dty.Doc_type_ID = pe.PD_doc_type and dt.DT_mode = 5
where dh.DH_doc_number = td.t_dh_doc_number and dh.DH_sub = 1
group by DH_doc_number
having count(dh.Doc_header_ID) = 1
) dh
on dh.DH_doc_number = td.t_dh_doc_number;
Using a join also means that you do not update the values where the condition does not match. If you use a left join, then the values will be updated to NULL (if that is your intention).
I'm not sure I believe you are getting more than one id back with that select given that you are doing a 'min' on it and have no group by. It should be only returning the lowest value for Doc_header_id.
To do what you are asking, first, you should have some way of joining to the tt_t_documents table in the update statement (eg. where td.id == tt_t_documents.id).
Second, you could re-write it to use the sub-query in the from. Something like:
update
tt_t_documents
set
t_Doc_header_ID = x.Doc_Header_id
from tt_t_documents join (
select td.id,
min(dh.Doc_header_ID)
from
tt_t_documents td
join Doc_header dh
on dh.DH_doc_number = td.t_dh_doc_number
and dh.DH_sub = 1
join Pred_entry pe
on pe.Pred_entry_ID = dh.DH_pred_entry
join Doc_type dt
on dty.Doc_type_ID = pe.PD_doc_type
and dt.DT_mode = 5
group by td.id
having
count(dh.Doc_header_ID) = 1
) x on tt_t_documents.id= x.id;
The syntax may not be perfect and I'm not sure how you want to find the doc_header_id but it would be something like this. The sub query would only return values with 1 doc_header_id). Not knowing the schema of your tables, this is as close as I can get.

Simplify update-statement

I have the fallowing update-statement:
update tmp set
tmp.Anzahl=(select sum(a.BNANZ) from PAYMASTER_Journal a where a.BNARTID=tmp.ArtikelAutoID),
tmp.Betrag=(select sum(a.BNBETR) from PAYMASTER_Journal a where a.BNARTID=tmp.ArtikelAutoID),
tmp.Rabatt=(select sum(a.BNRMRBETR) from PAYMASTER_Journal a where a.BNARTID=tmp.ArtikelAutoID)
from ##tmp1 tmp
On this way, for each record in ##tmp1, there are 3 subqueries executed. ##tmp1 contains 10'000 records -> totaly 30'000 subqueries.
Because each subquery selects the same records from PAYMASTER_Journal, I am searching for a way, to update ##tmp1 with executing only one subquery per record in ##tmp1.
I hope, someone can help me about this.
Using LEFT JOIN try this
update tmp set
tmp.Anzahl=BNANZ_accumulated,
tmp.Betrag=BNBETR_accumulated,
tmp.Rabatt=BNRMRBETR_accumulated
from ##tmp1 tmp
LEFT JOIN ( SELECT BNARTID,
SUM(BNANZ) AS BNANZ_accumulated,
SUM(BNBETR) AS BNBETR_accumulated,
SUM(BNRMRBETR) AS BNRMRBETR_accumulated
FROM PAYMASTER_Journal
WHERE (ARTIKELAUSWAHL=0x30 AND BLBONSTO=0x30 AND BLZESTO=0x30 AND
STORNO=0x30 AND
BDDAT BETWEEN '20120301' AND '20130821' AND
AdressID='d68e4d8f-e60e-4482-9730-76076948df43' AND
BNFIL=5 AND
ISNULL(Preisliste, 'VK-Preisliste') = 'VK-Preisliste' AND
BNARTID=tmp.ArtikelAutoID)
GROUP BY BNARTID) a ON a.BNARTID=tmp.ArtikelAutoID
this will leave you NULL when there is no rows in PAYMASTER_Journal for a given ##tmp1.ArtikelAutoID
if you don't want to touch them, change the LEFT JOIN to INNER JOIN
I'd go with MERGE statement:
merge ##tmp1
using (select
BNARTID
,sum(BNANZ) as BNANZ
,sum(BNBETR) as BNBETR
,sum(BNRMRBETR) as BNRMRBETR
from
PAYMASTER_Journal
group by
BNARTID
) as upd
on tmp.ArtikelAutoID = upd.BNARTID
when matched then update set Anzahl=BNANZ, Betrag=BNBETR, Rabatt=BNRMRBETR;
You can do it with a single sub-query as follows.
UPDATE tmp T
INNER JOIN
(SELECT a.BNARTID
,sum(a.BNANZ) as BANAZ_SUM
,sum(a.BNBETR) as BNBETR_SUM
,sum(a.BNRMRBETR) as BNRMRBETR_SUM
FROM PAYMASTER_Journal a
WHERE a.BNARTID = tmp.ArtikelAutoID
GROUP BY
a.BNARTID
) SQ
ON SQ.BNARTID = tmp.ArtikelAutoID
SET tmp.Anzahl = SQ.BANAZ_SUM
,tmp.Betrag = SQ.BNBETR_SUM
,tmp.Rabatt = SQ.BNRMRBETR_SUM

Column is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause

Ok here's my View (vw_LiftEquip)
SELECT dbo.tbl_equip_swl_unit.unit_id,
dbo.tbl_equip_swl_unit.unit_name,
dbo.tbl_equip_swl_unit.archived,
dbo.tbl_categories.category_id,
dbo.tbl_categories.categoryName,
dbo.tbl_categories.parentCategory,
dbo.tbl_categories.sub_category,
dbo.tbl_categories.desc_category,
dbo.tbl_categories.description,
dbo.tbl_categories.miscellaneous,
dbo.tbl_categories.category_archived,
dbo.tbl_equip_swl_unit.unit_name AS Expr1,
dbo.tbl_categories.categoryName AS Expr2,
dbo.tbl_categories.description AS Expr3,
dbo.tbl_equip_depts.dept_name,
dbo.tbl_equip_man.man_name,
dbo.tbl_Lifting_Gear.e_defects AS Expr7,
dbo.tbl_Lifting_Gear.e_defects_desc AS Expr8,
dbo.tbl_Lifting_Gear.e_defects_date AS Expr9,
dbo.tbl_equipment.equipment_id,
dbo.tbl_equipment.e_contract_no,
dbo.tbl_equipment.slID,
dbo.tbl_equipment.e_entered_by,
dbo.tbl_equipment.e_serial,
dbo.tbl_equipment.e_model,
dbo.tbl_equipment.e_description,
dbo.tbl_equipment.e_location_id,
dbo.tbl_equipment.e_owner_id,
dbo.tbl_equipment.e_department_id,
dbo.tbl_equipment.e_manafacture_id,
dbo.tbl_equipment.e_manDate1,
dbo.tbl_equipment.e_manDate2,
dbo.tbl_equipment.e_manDate3,
dbo.tbl_equipment.e_dimensions,
dbo.tbl_equipment.e_test_no,
dbo.tbl_equipment.e_firstDate1,
dbo.tbl_equipment.e_firstDate2,
dbo.tbl_equipment.e_firstDate3,
dbo.tbl_equipment.e_prevDate1,
dbo.tbl_equipment.e_prevDate2,
dbo.tbl_equipment.e_prevDate3,
dbo.tbl_equipment.e_insp_frequency,
dbo.tbl_equipment.e_swl,
dbo.tbl_equipment.e_swl_unit_id,
dbo.tbl_equipment.e_swl_notes,
dbo.tbl_equipment.e_cat_id,
dbo.tbl_equipment.e_sub_id,
dbo.tbl_equipment.e_parent_id,
dbo.tbl_equipment.e_last_inspector,
dbo.tbl_equipment.e_last_company,
dbo.tbl_equipment.e_deleted AS Expr11,
dbo.tbl_equipment.e_deleted_desc AS Expr12,
dbo.tbl_equipment.e_deleted_date AS Expr13,
dbo.tbl_equipment.e_deleted_insp AS Expr14,
dbo.tbl_Lifting_Gear.e_defects_action AS Expr15,
dbo.tbl_equipment.e_rig_location,
dbo.tbl_Lifting_Gear.e_add_type AS Expr17,
dbo.tbl_Lifting_Gear.con_id,
dbo.tbl_Lifting_Gear.lifting_date,
dbo.tbl_Lifting_Gear.lifting_ref_no,
dbo.tbl_Lifting_Gear.e_id,
dbo.tbl_Lifting_Gear.inspector_id,
dbo.tbl_Lifting_Gear.lift_testCert,
dbo.tbl_Lifting_Gear.lift_rig_location,
dbo.tbl_Lifting_Gear.inspected,
dbo.tbl_Lifting_Gear.lifting_through,
dbo.tbl_Lifting_Gear.liftingNDT,
dbo.tbl_Lifting_Gear.liftingTest,
dbo.tbl_Lifting_Gear.e_defects,
dbo.tbl_Lifting_Gear.e_defects_desc,
dbo.tbl_Lifting_Gear.e_defects_date,
dbo.tbl_Lifting_Gear.e_defects_action,
dbo.tbl_Lifting_Gear.lift_department_id,
dbo.tbl_Lifting_Gear.lifting_loc
FROM dbo.tbl_equipment
INNER JOIN dbo.tbl_equip_swl_unit
ON dbo.tbl_equipment.e_swl_unit_id = dbo.tbl_equip_swl_unit.unit_id
INNER JOIN dbo.tbl_categories
ON dbo.tbl_equipment.e_cat_id = dbo.tbl_categories.category_id
INNER JOIN dbo.tbl_equip_depts
ON dbo.tbl_equipment.e_department_id = dbo.tbl_equip_depts.dept_id
INNER JOIN dbo.tbl_equip_man
ON dbo.tbl_equipment.e_manafacture_id = dbo.tbl_equip_man.man_id
INNER JOIN dbo.vwSubCategory
ON dbo.tbl_equipment.e_sub_id = dbo.vwSubCategory.category_id
INNER JOIN dbo.vwDescCategory
ON dbo.tbl_equipment.e_cat_id = dbo.vwDescCategory.category_id
INNER JOIN dbo.tbl_Lifting_Gear
ON dbo.tbl_equipment.equipment_id = dbo.tbl_Lifting_Gear.e_id
And here's the select statement with subquery that I am using:
SELECT *
FROM vw_LiftEquip
WHERE lifting_loc = ? AND
con_id = ? AND
EXPR11 =
'N'(
SELECT MAX(lifting_date) AS maxLift
FROM vw_LiftEquip
WHERE e_id = equipment_id
)
ORDER BY lifting_ref_no,
category_id,
e_swl,
e_serial
I get the error :
Column "vw_LiftEquip.category_id" is invalid in the ORDER BY clause because it is not contained in either an aggregate function or the GROUP BY clause.
Can't see why its returning that error, this is admittedly the first time I've ran a subquery on such a complex view, and I am a bit lost, thanks in advance for any help. I have looked through the similar posts and can find no answers to this one, sorry if I am just being dumb.
You are missing AND between EXPR11 = 'N' and (SELECT MAX(...
Otherwise, it looks OK. MAX without GROUP BY is allowed if you have no other columns in the SELECT
Update: #hvd also noted that you have nothing to compare to MAX(lifting_date). See comment
Update 2,
SELECT *
FROM vw_LiftEquip v1
CROSS JOIN
(
SELECT MAX(lifting_date) AS maxLift
FROM vw_LiftEquip
WHERE e_id = equipment_id
) v2
WHERE v1.lifting_loc = ? AND
v1.con_id = ? AND
v1.EXPR11 = 'N'
ORDER BY v1.lifting_ref_no,
v1.category_id,
v1.e_swl,
v1.e_serial