I need to run an update on a SQL table, using a value from a different (but almost identical) row in the same table, to show how different sales scenarios play out.
e.g.
Starting with:
ITEM, SITE, SUPPLIER, SCENARIO, SALES_VOLUME, PRICE, TOTAL_SALES
1 , A , X , S1 , 100 , 10 , 1000
2 , A , Y , S1 , 25 , 20 , 500
1 , A , X , S2 , {blank} , 20 , 0
I would like to update to show:
ITEM, SITE, SUPPLIER, SCENARIO, SALES_VOLUME, PRICE, TOTAL_SALES
1 , A , X , 1 , 100 , 10 , 1000
2 , A , Y , 1 , 25 , 20 , 500
1 , A , X , 2 , {blank} , 20 , 2000
So basically, if SCENARIO = S2, I need to recalculate using SALES_VOLUME where SCENARIO = S1
I tried the following, but it didn't work - I think because I'm trying to specify both =1 and !=1 in the same lookup.
UPDATE TABLE1
SET [TOTAL_SALES] = (t1.[PRICE] * t2.[SALES_VOLUME])
FROM TABLE1 t1
inner join TABLE1 t2
on t1.[ITEM] = t2.[ITEM]
and t1.[SITE] = t2.[SITE]
and t1.[SUPPLIER] = t2.[SUPPLIER]
and t1.[SCENARIO] = 'S1'
WHERE t1.[SCENARIO] != 'S1'
I don't think I'm too far off, but just feel I'm missing something.
Any pointers would be gratefully received. :)
You may try this -
UPDATE t1
SET [TOTAL_SALES] = (t1.[PRICE] * t2.[SALES_VOLUME])
FROM TABLE1 t1
inner join TABLE1 t2
on t1.[ITEM] = t2.[ITEM]
and t1.[SITE] = t2.[SITE]
and t1.[SUPPLIER] = t2.[SUPPLIER]
and t1.[SCENARIO] = 'S2'
WHERE t2.[SCENARIO] = 'S1';
Related
How would I implement a group by to this?
Tried just grouping by everything in the select and it doesn't appear to work.
SELECT SL.ORDER_NO,
SL.HANDLING_UNIT_ID,
HUS.MANUAL_GROSS_WEIGHT,
SL.OBJVERSION,
ACCOUNTING_PERIOD_API.GET_PERIOD_DESCRIPTION(SITE_API.GET_COMPANY(SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID)),
ACCOUNTING_PERIOD_API.GET_CURR_ACC_YEAR(SITE_API.GET_COMPANY(SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID))),
ACCOUNTING_PERIOD_API.GET_CURR_ACC_PERIOD(SITE_API.GET_COMPANY(SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID)))) ACC_DESC,
HUS.WIDTH,
HUS.HEIGHT,
HUS.DEPTH,
SL.QUANTITY * IFSAPP.HANDLING_UNIT_API.GET_TARE_WEIGHT(HUS.HANDLING_UNIT_ID, HUS.UOM_FOR_WEIGHT) TOTAL_WEIGHT_KGS,
HUS.HANDLING_UNIT_TYPE_ID CASE_NOS,
HUS.WIDTH * HUS.HEIGHT * HUS.DEPTH DIMENSIONS,
HUS.WIDTH * HUS.HEIGHT * HUS.DEPTH * 3 / 1000000 TOTAL_CUBE_BOX
FROM SHIPMENT_LINE_HANDL_UNIT SL
JOIN HANDLING_UNIT_SHIPMENT_CFV HUS
ON HUS.SHIPMENT_ID = SL.SHIPMENT_ID
JOIN SHIPMENT S
ON S.SHIPMENT_ID = SL.SHIPMENT_ID
JOIN CUSTOMER_ORDER CO
ON CO.ORDER_NO = S.ORDER_NO
WHERE SHIPMENT_API.GET_STATE(HUS.SHIPMENT_ID) = 'Completed'
AND SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID) = '1314'
AND SL.HANDLING_UNIT_ID = HUS.HANDLING_UNIT_ID
AND S.SHIP_VIA_CODE = 'SEA'
AND CO.REGION_CODE = 'AM'
Expected data:
Shiptrain7 1 102 102 111x93x106 RPL111x93x106 93 111 106 3.28
Shiptrain7 1 57 57 111x93x106 RPL111x93x106 93 111 106 3.28
Shiptrain8 1 150 150 111x93x106 RPL111x93x106 93 111 106 3.28
Shiptrain8 1 2 2 35x26x33 RPL35x26x33 26 35 33 3.28
There is just one of each case, the handling unit id is associated to each case. Its bringing the actual ID rather than amount of each case which is 1. Also, this is being used in a crystal report so ignore the fields which arent needed.
You want to GROUP BY everything in the projection except the handling_unit_id, which you just want to count. You could alter the existing query, but you have a large number of derived columns which will make the GROUP BY clause complicated and brittle.
So you should wrap the existing query in another query which you can use for aggregation. Note that you must give an alias to each column in the query.
select order_no
, count(handling_unit_id) as no_of_units
, manual_gross_weight
, objversion
, acct_period_description
, acct_period
, acc_desc
, width
, height
, depth
, total_weight_kgs
, case_nos
, dimensions
, total_cube_box
from (
SELECT SL.ORDER_NO,
SL.HANDLING_UNIT_ID,
HUS.MANUAL_GROSS_WEIGHT,
SL.OBJVERSION,
ACCOUNTING_PERIOD_API.GET_PERIOD_DESCRIPTION(SITE_API.GET_COMPANY(SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID)) as acct_period_description,
ACCOUNTING_PERIOD_API.GET_CURR_ACC_YEAR(SITE_API.GET_COMPANY(SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID))) as acct_period,
ACCOUNTING_PERIOD_API.GET_CURR_ACC_PERIOD(SITE_API.GET_COMPANY(SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID)))) ACC_DESC,
HUS.WIDTH,
HUS.HEIGHT,
HUS.DEPTH,
SL.QUANTITY * IFSAPP.HANDLING_UNIT_API.GET_TARE_WEIGHT(HUS.HANDLING_UNIT_ID, HUS.UOM_FOR_WEIGHT) TOTAL_WEIGHT_KGS,
HUS.HANDLING_UNIT_TYPE_ID CASE_NOS,
HUS.WIDTH * HUS.HEIGHT * HUS.DEPTH DIMENSIONS,
HUS.WIDTH * HUS.HEIGHT * HUS.DEPTH * 3 / 1000000 TOTAL_CUBE_BOX
FROM SHIPMENT_LINE_HANDL_UNIT SL
JOIN HANDLING_UNIT_SHIPMENT_CFV HUS
ON HUS.SHIPMENT_ID = SL.SHIPMENT_ID
JOIN SHIPMENT S
ON S.SHIPMENT_ID = SL.SHIPMENT_ID
JOIN CUSTOMER_ORDER CO
ON CO.ORDER_NO = S.ORDER_NO
WHERE SHIPMENT_API.GET_STATE(HUS.SHIPMENT_ID) = 'Completed'
AND SHIPMENT_API.GET_CONTRACT(HUS.SHIPMENT_ID) = '1314'
AND SL.HANDLING_UNIT_ID = HUS.HANDLING_UNIT_ID
AND S.SHIP_VIA_CODE = 'SEA'
AND CO.REGION_CODE = 'AM'
)
group by order_no
, manual_gross_weight
, objversion
, acct_period_description
, acct_period
, acc_desc
, width
, height
, depth
, total_weight_kgs
, case_nos
, dimensions
, total_cube_box
I am having this issue with making consolidate for rows, I have made the query, but the result aren't correct.
It may consolidate the rows but for some result it will divide them into two different rows , what i need is to make them all in one row only if the id
is matching.
And here is the query :
Select
trxTransactionSaleItem.TransactionKey
, 'Sale' As TrxnType
, InvProduct.Id
, InvProduct.UPC
, trxTransactionSaleItem.Description
, invproduct.Description2
, invProduct.ProductGroupKey
, sum (Quantity/ISNULL(UOMBaseQuantity,1)) as Quantity
, Price
, SUM(DiscountAmount) AS DA
, SUM(SurchargeTotal) AS ST
, sum (Total) as Total
, ISNULL(UOM.Description,'') as UOM
From
trxTransactionSaleItem
INNER JOIN
InvProduct on trxTransactionSaleItem.ProductKey = InvProduct.ProductKey
LEFT JOIN
InvUOMGroupDetail UOMD on UOMGroupDetailKey = UOMD.UOMGroupDetailKey
LEFT JOIN
InvUOM UOM on UOMD.UOMKey = UOM.UOMKey
Where
Type = 0
And IsExchange = 0
And trxTransactionSaleItem.TransactionKey = 60000000022537
group by
trxTransactionSaleItem.TransactionKey
, InvProduct.Id
, InvProduct.UPC
, trxTransactionSaleItem.Description
, invproduct.Description2
, invProduct.ProductGroupKey
, Quantity
, Price
, DiscountAmount
, SurchargeTotal
, Total
, UOM.Description
So why its not coming in one row ?
Your group by should have only the fields that are not in aggregation functions. It should look like:
group by trxTransactionSaleItem.TransactionKey,
InvProduct.Id,
InvProduct.UPC,
trxTransactionSaleItem.Description,
invproduct.Description2,
invProduct.ProductGroupKey,
Price,
ISNULL(UOM.Description, '')
I have 2 different query.Is it possible combine these query ? If it is possible how can I do it ?
Query 1 : http://pastebin.com/pAdP9Yub
SELECT LatofTruck=Lat, LngofTruck=Lng, SpeedofTruck=Speed
FROM TruckLocation
JOIN Truck AS Trucks ON Trucks.OID=TruckLocation.TruckID
WHERE TruckLocation.OID
IN (
SELECT MAX(TruckLocation_1.OID) AS OID
FROM TruckLocation AS TruckLocation_1
JOIN Truck ON TruckLocation_1.TruckID = Truck.OID GROUP BY
TruckLocation_1.TruckID
)
ORDER BY TruckLocation.ReadTime DESC
Query 2 :http://pastebin.com/Esx36JHU
SELECT a_TankLevel1,a_TankLevel2,d_AlertStation,StateOutAlarm,StateOutValve,
SensorDataPackage.DeviceID,Branch.FirmName,LatofDealer=Branch.Lat,
LngofDealer=Branch.Lng,Branch.City,Branch.FirmPhone,Branch.DealerAdmin
FROM SensorDataPackage
JOIN Dealer AS Branch ON Branch.DeviceID=SensorDataPackage.DeviceID
WHERE SensorDataPackage.OID
IN (
SELECT MAX (SensorDataPackage.OID)
FROM SensorDataPackage
WHERE SensorDataPackage.readTime > DATEADD(DAY,-100,GETDATE())
GROUP BY SensorDataPackage.DeviceID
)
ORDER BY SensorDataPackage.readTime DESC
You can use UNION ALL for this but you have to make sure you have the same number of columns and column types. So:
select a, b, c, from x
union all
select p, q, r, s, t from y
doesn't work but
select a, b, p, q, t from x
union all
select a, b, p, q, t from y
will work.
So in your case, you'd get something like this:
-- First query.
SELECT Latitude = Lat
, Longitude = Lng
, SpeedofTruck = Speed
, a_TankLevel1 = null
, a_TankLevel2 = null
, d_AlertStation = null
, StateOutAlarm = null
, StateOutValve = null
, DeviceID = null
, FirmName = null
, City = null
, FirmPhone = null
, DealerAdmin = null
FROM TruckLocation
JOIN Truck AS Trucks ON Trucks.OID=TruckLocation.TruckID
WHERE TruckLocation.OID
IN (
SELECT MAX(TruckLocation_1.OID) AS OID
FROM TruckLocation AS TruckLocation_1
JOIN Truck ON TruckLocation_1.TruckID = Truck.OID GROUP BY
TruckLocation_1.TruckID
)
UNION ALL
-- Second query.
SELECT Latitude = Branch.Lat
, Longitude = Branch.Lng
, SpeedofTruck = null
, a_TankLevel1
, a_TankLevel2
, d_AlertStation
, StateOutAlarm
, StateOutValve
, SensorDataPackage.DeviceID
, Branch.FirmName
, Branch.City
, Branch.FirmPhone
, Branch.DealerAdmin
FROM SensorDataPackage
JOIN Dealer AS Branch ON Branch.DeviceID=SensorDataPackage.DeviceID
WHERE SensorDataPackage.OID
IN (
SELECT MAX (SensorDataPackage.OID)
FROM SensorDataPackage
WHERE SensorDataPackage.readTime > DATEADD(DAY,-100,GETDATE())
GROUP BY SensorDataPackage.DeviceID
)
This will give you a result set that has latitude and longitude for both trucks and branches.
Hi Common Table Expression would help you in such cases. If you have some common factor between both the tables, you can bring them into a same query and get data in to single query. I have used this feature several times. View is also a very good alternative solution for this.
I am trying to implement this query but I can’t figure out why I am not getting the result.
Here are the descriptions:
Lets say I have a table call: TableAct
Acct# Date WithdrawAmt DepositAmt
!24455 2012-11-19-00.00.00 1245.77 200.50
125577 2011-02-12-00.00.00 100.98 578.00
Another table TableCustomerOrd:
ID# COrder# CustID Ord_Description VendorType
124455 7712AS 123 1AAA Permanent
125577 9914DL 346 1BBB Partial
... UK1234 111 2HJ5 Permanent'
,,, FR0912 567 5LGY Partial
Then TableCustomerDtls:
CustID Descriptions Delivery Address ZipCode
123 1AAA_BLUESHARE SUCCESSFUL 222 Main St 97002
346 1BBB_CHASE DECLINE 40 West Side 97122
111 2HJ5_CITIBANK SUCCESSFUL ……. …….
567 5LGY_VANGURD DECLINED ---- -----
And table DelivaryFlight:
FlightOrder# FlightCustID FlightDt
7712AS 123 2011-9-29-00.00.00
9914DL 346 2010-11-2-00.00.00
UK1234 111 2012-4-1-00.00.00
FR0912 567 2012-9-11-00.00.00
I want to update TableAct on the following conditions:
TableAct. Acct# = TableCustomerOrd.ID#, AND:
TableCustomerOrd. CustID = TableCustomerDtls.CustID and at the same time, TableCustomerOrd.Ord_Descriptions field should match with TableCustomerDtls. Descriptions field anything before “_” . Therefore ‘1AAA’, ‘2HJ5’ etc. AND:
DelivaryFlight.FlightOrder# = TableCustomerOrd.COrder#, AND: DelivaryFlight.FlightCustID = TableCustomerOrd. CustID. Also TableCustomerDtls. Delivery = ‘SUCCESSFUL’ AND:
DelivaryFlight.FlightOrder# = TableCustomerOrd. COrder#
AND DelivaryFlight.FlightCustID = TableCustomerOrd. CustID
Also TableCustomerDtls. Delivery = ‘DECLINED
Then I want to compare: elivaryFlight.FlightDt > DelivaryFlight.FlightDt.
Basically I need to match table DelivaryFlight columns FlightOrder#, FlightCustID with TableCustomerOrd.
Moreover TableCustomerDtls column Delivery to ck for delivary status such as ‘DECLINED’.
And ‘SUCCESSFUL’ condition and compare ‘SUCCESSFUL’ FlightDt with ‘DECLINED’ FlightDt.
Here's my query but please help me to understand, I am sure this could be done in a better way.
The query is not working:
Update
Set …
FROM TableAct AC
Join TableCustomerOrd CustOd
ON AC.Acct# = CustOd.ID#
Join TableCustomerDtls CDtls
ON CDtls. CustID = CustOd. CustID
AND (CustOd.Ord_Descriptions =
Left(CDtls.Descriptions, LEN(rtrim(CDtls.Descriptions))))
JOIN DelivaryFlight DF
ON DF.FlightOrder# = CustOd.COrder#
AND DF.FlightCustID = CustOd.CustID
AND CDtls.Delivery = ‘SUCCESSFUL’
JOIN DelivaryFlight DF2
ON DF2.FlightOrder# = DF.COrder#
AND DF2.FlightCustID = DF.CustID
AND CDtls.Delivery = ‘DECLINED’
WHERE DelivaryFlight. FlightDt > DelivaryFlight. FlightDt
AND DepositAmt > 100
Your Help will be monumental 'cause my project due end of this week.
Thank you
If I have a complex query like this, I start by creating a "simple" select which produces only the rows to be updated.
It should also return both the update values and the pk for the updated table
It is then (relatively) straight forward to (inner) join this with the table to be updated and do the update remebering to only update matching rows by including
WHERE tblTobeUpdated.pk = SimpleSelect.pk
Hope this helps
I don't have the time to look at this in depth but I suspect you at least want to fix:
WHERE DelivaryFlight. FlightDt > DelivaryFlight. FlightDt
This is a condition that can never be met.
You probably want:
WHERE DF. FlightDt > DF2. FlightDt
it is also useful with these complex queires for an update to be able to see the records that would be updated, so I usually do something like this:
Update
Set …
--Select *
FROM TableAct AC
Then instead of running the update, I run just highlight and run the part that starts with select to see the results and don't test the update until I am sure I am selecting the records I want to select and that the values I will be replacing are correct.
Try breaking your query down, heres a query I wrote today, test each part separately
SELECT
Employee
, Reference
, Payroll
, [Hours] / 60
[Hours]
, [Days]
FROM
(
SELECT
Employee
, Reference
, Payroll
, SUM( Duration ) AS [Hours]
, AvailableID
FROM
(
SELECT
RequirerID
, Duration
, RTRIM( COALESCE(MA.MemberLastName, '')
+ ' ' + COALESCE(MA.MemberFirstName, '')
+ ' ' + COALESCE(MA.MemberInitial, '')) Employee
, COALESCE(MA.Detailref1, '') Reference
, COALESCE(MA.PayrollRef, '') Payroll
, Available.AvailableId
FROM
(
SELECT DISTINCT
RequirerID
, ShiftDate
, CAST(ShiftStart - ShiftEnd - ShiftBreak AS DECIMAL(19,2)) ShiftDuration
, Id RequirementRecordID
FROM
Requirements
WHERE
Requirements.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND RequirerID IN (SELECT ID FROM MemberDetails WHERE CompanyID = #ParamCompanyID)
)
R
INNER JOIN
ShiftConfirmed
INNER JOIN
Available
INNER JOIN
MemberDetails MA
ON Available.AvailableID = MA.ID
ON ShiftConfirmed.AvailableRecordID = Available.ID
ON R.RequirementRecordID = ShiftConfirmed.RequirementRecordID
WHERE
R.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND COALESCE(ShiftChecked, 0) BETWEEN 0 AND 1
)
ShiftDay
Group By
Employee
, Reference
, Payroll
, AvailableId
) Shifts
INNER JOIN
(
SELECT
COUNT( * ) AS [Days]
, AvailableID
FROM
(
SELECT DISTINCT
R.ShiftDate
, Available.AvailableId
FROM
(
SELECT DISTINCT
ShiftDate
, Id RequirementRecordID
FROM
Requirements
WHERE
Requirements.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND RequirerID IN (SELECT ID FROM MemberDetails WHERE CompanyID = #ParamCompanyID)
)
R
INNER JOIN
ShiftConfirmed
INNER JOIN
Available
INNER JOIN
MemberDetails MA
ON Available.AvailableID = MA.ID
ON ShiftConfirmed.AvailableRecordID = Available.ID
ON R.RequirementRecordID = ShiftConfirmed.RequirementRecordID
WHERE
R.ShiftDate BETWEEN #ParamStartDate
AND #ParamEndDate
AND COALESCE(ShiftChecked, 0) BETWEEN 0 AND 1
)
ShiftDay
Group By
AvailableId
) D
ON Shifts.AvailableID = D.AvailableID
WHERE [Hours] > 0
ORDER BY
Employee
I am experiencing very odd performance on DB2 version 9.1 when running the query below:
select a.CYCL_NUM
, a.AC_NUM
, a.AUTHS_DTE
, a.PL_ID
, a.APRVD_RSPN_CDE
, a.AUTHS_AMT
, a.AUTHS_STS_CDE
, a.TRAN_CTGR_CDE
, a.MRCHN_CTGR_CDE
, d.out_pu_au_amt
from nwhd12.chldr_auths a, nwhd12.w_chldr_ac d
where cycl_num = 200911
and a.ac_num = d.ac_num
and APRVD_RSPN_CDE = 'APV'
and not exists (
select 1 from auths_rev_hist b
where a.cycl_num = b.cycl_num
and a.auths_dte = b.auths_dte
and a.TRAN_CTGR_CDE = b.TRAN_CTGR_CDE
and a.PL_ID = b.pl_id
and a.APRVD_RSPN_CDE = b.APRVD_RSPN_CDE
and a.AUTHS_AMT = b.auths_amt
and a.TRAN_CTGR_CDE = b.TRAN_CTGR_CDE
and a.MRCHN_CTGR_CDE = MRCHN_CTGR_CDE
)
;
What is supposed to happen is that the query accesses partion 97 of nwhd12.chldr_auths, since that is the partition corresponding to cycle 200911. Instead, after accessing partition 97, it starts accessing every other partition in nwhd12.chldr_auths. Now, I was told that this is because of the "WHERE NOT EXISTS", but there is still the restriction on cycles in this statement (a.cycl_num = b.cycl_num), so why is it scanning all the partitions?
If I hard code the cycle in the where not exists, then the query performs as expected.
Thanks,
Dave
if the planner is this easily confused, you need to try a few different formulations. this untested (I don't even have DB2, but CTEs originated there):
WITH hist AS (
cycl_num
, ac_num
, auths_dte
, pl_id
, aprvd_rspn_cde
, auths_amt
, auths_sts_cde
, tran_ctgr_cde
, mrchn_ctgr_cde
FROM auths_rev_hist b
)
, auths AS (
SELECT
cycl_num
, ac_num
, auths_dte
, pl_id
, aprvd_rspn_cde
, auths_amt
, auths_sts_cde
, tran_ctgr_cde
, mrchn_ctgr_cde
FROM nwhd12.chldr_auths
WHERE cycl_num = 200911
AND aprvd_rspn_cde = 'APV'
EXCEPT
SELECT ... FROM hist
)
SELECT a.*, d.out_pu_au_amt
FROM auths a, nwhd12.w_chldr_ac d
WHERE a.ac_num = d.ac_num