Oracle update subquery of records - oracle

I need to update a list of record given by a subquery, sniffing around on the web I tried this structure:
UPDATE
(
SELECT
a.COL1
FROM
TABLE1 a,
TABLE2 b
WHERE
a.field1 = b.field1
) update_tbl
SET
update_tbl.COL1 = 'VALUE'
But it returns to me this Oracle error:
-> ORA-01779: Cannot modify a column which maps to a non key-preserved table
My query is the following one:
UPDATE
(
SELECT
imp.*
FROM table1 imp
JOIN table2 sp ON imp.id_p = sp.id_p
JOIN table3 cs ON sp.id_s = cs.id_s
JOIN table4 cb ON cb.id_c = cs.id_c
WHERE
imp.id_b = cb.id_b
AND (
(to_char(imp.p,'yyyymm') < to_char(cb.data_in,'yyyymm')) OR
(cb.data_fi IS NOT NULL AND to_char(imp.p,'yyyymm') > to_char(cb.data_fi,'yyyymm'))
)
and (
(imp.v is not null) or
(imp.v_s is not null and imp.v_s <> 0) or
(imp.imp_co is not null and imp.imp_co <> 0) or
(imp.imp_acc is not null and imp.imp_acc <> 0)
)
) i
SET
i.v = null,
i.v_s = 0,
i.imp_co = 0,
i.imp_acc = 0,
i.ID_S_CONT = 'N',
i.ID_T_COMP = 'P',
i.date_upd = SYSDATE,
i.user_upd = 'SeR'
The subquery return 82 rows (tested now), and I do want to modify only that rows, What am I doing wrong?

I think you are updating to imp table. so you can try MERGE like below
MERGE INTO
IMP A
USING
( SELECT
imp.*
FROM table1 imp
JOIN table2 sp ON imp.id_p = sp.id_p
JOIN table3 cs ON sp.id_s = cs.id_s
JOIN table4 cb ON cb.id_c = cs.id_c
WHERE
imp.id_b = cb.id_b
AND (
(to_char(imp.p,'yyyymm') < to_char(cb.data_in,'yyyymm')) OR
(cb.data_fi IS NOT NULL AND to_char(imp.p,'yyyymm') >
to_char(cb.data_fi,'yyyymm'))
)
and (
(imp.v is not null) or
(imp.v_s is not null and imp.v_s <> 0) or
(imp.imp_co is not null and imp.imp_co <> 0) or
(imp.imp_acc is not null and imp.imp_acc <> 0)
)) B
ON (A.ID =B.ID)
WHEN MATCHED THEN
UPDATE SET
A.v = null,
A.v_s = 0,
A.imp_co = 0,
A.imp_acc = 0,
A.ID_S_CONT = 'N',
A.ID_T_COMP = 'P',
A.date_upd = SYSDATE,
A.user_upd = 'SeR'
Will update the table given by subquery. here A.ID =B.ID use the primary key.

Related

I want to add a subquery with a date parameter to return a calculated value but my query is not working

I have a query that fetches data from oracle inventory and purchasing. Now I want to add a subquery from po_line_locations_all with a date parameter to return a calculated value as if the value lies in the subquery show it else display zero, But in my case the query shows nothing if subquery returns null.
I want to show the result of the main query even if subquery returns null.
SELECT distinct msib.segment1 Item_Code,
MSIB.inventory_item_id,
MSIB.organization_id ORG_ID,
msib.description Item_Description,
msib.primary_unit_of_measure UOM,
ph.attribute1 Item_Type,
SUM(plla.quantity) - SUM(plla.quantity_received) On_Order,
ph.currency_code currency,
max(pl.unit_price) FOB_Value_in_FCY,
max(ph.rate_date),
max(ph.rate) forex_rate,
(
SELECT SUM (moq.transaction_quantity)
FROM mtl_system_items_b msi, mtl_onhand_quantities moq
WHERE moq.organization_id(+) = msi.organization_id
AND moq.inventory_item_id(+) = msi.inventory_item_id
and moq.ORGANIZATION_ID =MSIB.organization_id
and msi.inventory_item_id = MSIB.inventory_item_id
GROUP BY msi.segment1, msi.organization_id
) CURR_STOCK,
(
SELECT NVL(ABS(sum(mtmt.transaction_quantity)),0) from MTL_MATERIAL_TRANSACTIONS mtmt
WHERE 1=1
AND mtmt.inventory_item_id = MSIB.inventory_item_id --4018
AND mtmt.organization_id = MSIB.organization_id--499
and mtmt.TRANSACTION_ACTION_ID NOT IN (24, 30)
AND to_date(mtmt.transaction_date) >= to_date(&Roll_back_date,'DD-MON-RRRR')
)RB_TRANSACTIONS,
(
select ABS(SUM(mmt.transaction_quantity))
from MTL_MATERIAL_TRANSACTIONS mmt
where mmt.TRANSACTION_ACTION_ID NOT IN (24, 30)
and (mmt.ORGANIZATION_ID = MSIB.organization_id --499--579
)
and (mmt.INVENTORY_ITEM_ID = MSIB.inventory_item_id --4128 --4165
and mmt.TRANSACTION_TYPE_ID in (33, 52)
)
and (mmt.transaction_date between
to_date(add_months(&CONS_f_DATE, -12),'DD-MON-YYYY')
AND to_date(&CONS_f_DATE, 'DD-MON-YYYY')
)
AND (mmt.parent_transaction_id IS NULL)
) annual_Consumption,
(
select ABS(SUM(mmt.transaction_quantity) / 4)
FROM MTL_MATERIAL_TRANSACTIONS mmt
WHERE mmt.TRANSACTION_ACTION_ID NOT IN (24, 30)
and (mmt.ORGANIZATION_ID = MSIB.organization_id --499--579
)
and (mmt.INVENTORY_ITEM_ID = MSIB.inventory_item_id --4128 --4165
AND mmt.TRANSACTION_TYPE_ID in (33, 52)
)
and (mmt.transaction_date between
to_date(add_months(&CONS_f_DATE, -12),
'DD-MON-YYYY') AND
to_date(&CONS_f_DATE, 'DD-MON-YYYY'))
AND (mmt.parent_transaction_id IS NULL)
) months_Consumption,
(
select ABS((SUM(mmt.transaction_quantity) / 4) / 3)
FROM MTL_MATERIAL_TRANSACTIONS mmt
WHERE mmt.TRANSACTION_ACTION_ID NOT IN (24, 30)
and (mmt.ORGANIZATION_ID = MSIB.organization_id --499--579
)
and (mmt.INVENTORY_ITEM_ID = MSIB.inventory_item_id --4128 --4165
AND mmt.TRANSACTION_TYPE_ID in (33, 52))
and (mmt.transaction_date between
to_date(add_months(&CONS_f_DATE, -12),
'DD-MON-YYYY') AND
to_date(&CONS_f_DATE, 'DD-MON-YYYY'))
AND (mmt.parent_transaction_id IS NULL)
) monthly_Average,
(
select MATERIAL_COST
FROM CST_ITEM_COST_TYPE_V vw
WHERE vw.organization_id = MSIB.organization_id
AND - 1 = -1
and (vw.INVENTORY_ITEM_ID = MSIB.inventory_item_id)
) Unit_Cost, --new
sum(quan.t_quantity) - sum(r_quantity) finala
FROM mtl_system_items_b MSIB,
PO_HEADERS_ALL ph,
Po_Lines_All pl,
PO_LINE_LOCATIONS_ALL PLLA,
-------------------SUBQUERY---------------------------------------
(select nvl(sum(subplla.quantity),0) t_quantity, nvl(sum(subplla.quantity_received),0) r_quantity ,subpl.item_id
from po_headers_all subph,
po_lines_all subpl,
po_line_locations_all subplla
where subph.po_header_id = subpl.po_header_id
and subplla.po_header_id = subph.po_header_id
and subpl.po_line_id = subplla.po_line_id
and subplla.org_id = subpl.org_id
and to_date(subplla.creation_date) >= to_date(&Roll_back_date,'DD-MON-RRRR')
group by subph.attribute1, subph.currency_code, subpl.item_id
) quan
-------------------SUBQUERY---------------------------------------
WHERE 1=1
and ph.po_header_id = pl.po_header_id
and msib.inventory_item_id (+) = pl.item_id
and pl.item_id (+) = quan.item_id
and plla.po_header_id = ph.po_header_id
and pl.po_line_id = plla.po_line_id
and plla.org_id = pl.org_id
and msib.organization_id in
(select haou.organization_id
from hr_organization_information hoi,
hr_all_organization_units haou
where haou.organization_id = hoi.organization_id
and hoi.org_information1 = 'INV'
and hoi.org_information2 = 'Y'
and haou.name like '%HEIS%')
and MSIB.Inventory_Item_Id=NVL(&ITEM,MSIB.Inventory_Item_Id)
and MSIB.organization_id = nvl(&P_ORGI, MSIB.organization_id)
AND to_date(plla.creation_date) BETWEEN
to_date(add_months(&Roll_back_date, -12),'DD-MON-YYYY') AND
to_date(&Roll_back_date,'DD-MON-YYYY')
GROUP BY msib.segment1,
MSIB.inventory_item_id,
msib.description,
MSIB.organization_id,
msib.primary_unit_of_measure,
ph.attribute1,
ph.currency_code
My guess is that your problem is simply using old-syntax joins instead of something that has been around for a really long time.
SELECT DISTINCT msib.segment1 Item_Code,
MSIB.inventory_item_id,
MSIB.organization_id ORG_ID,
msib.description Item_Description,
msib.primary_unit_of_measure UOM,
ph.attribute1 Item_Type,
SUM(plla.quantity) - SUM(plla.quantity_received) On_Order,
ph.currency_code currency,
max(pl.unit_price) FOB_Value_in_FCY,
max(ph.rate_date),
max(ph.rate) forex_rate,
(
SELECT SUM(moq.transaction_quantity)
FROM mtl_system_items_b msi
RIGHT JOIN mtl_onhand_quantities moq ON moq.organization_id = msi.organization_id
AND moq.inventory_item_id = msi.inventory_item_id
WHERE moq.ORGANIZATION_ID = MSIB.organization_id
AND msi.inventory_item_id = MSIB.inventory_item_id
GROUP BY msi.segment1,
msi.organization_id
) CURR_STOCK,
(
SELECT NVL(ABS(sum(mtmt.transaction_quantity)), 0)
FROM MTL_MATERIAL_TRANSACTIONS mtmt
WHERE 1 = 1
AND mtmt.inventory_item_id = MSIB.inventory_item_id --4018
AND mtmt.organization_id = MSIB.organization_id --499
AND mtmt.TRANSACTION_ACTION_ID NOT IN (24,30)
AND to_date(mtmt.transaction_date) >= to_date(&Roll_back_date, 'DD-MON-RRRR')
) RB_TRANSACTIONS,
mmt.annual_Consumption annual_Consumption,
mmt.annual_Consumption / 4 months_Consumption,
mmt.annual_Consumption / 12 monthly_Average,
(
SELECT MATERIAL_COST
FROM CST_ITEM_COST_TYPE_V vw
WHERE vw.organization_id = MSIB.organization_id
AND vw.INVENTORY_ITEM_ID = MSIB.inventory_item_id
) Unit_Cost, --new
sum(quan.t_quantity) - sum(r_quantity) finala
FROM mtl_system_items_b MSIB
LEFT JOIN PO_HEADERS_ALL ph ON msib.inventory_item_id = pl.item_id
INNER JOIN Po_Lines_All pl ON ph.po_header_id = pl.po_header_id
INNER JOIN PO_LINE_LOCATIONS_ALL PLLA ON plla.po_header_id = ph.po_header_id AND pl.po_line_id = plla.po_line_id AND plla.org_id = pl.org_id
LEFT JOIN
-------------------SUBQUERY---------------------------------------
(
SELECT nvl(sum(subplla.quantity), 0) t_quantity,
nvl(sum(subplla.quantity_received), 0) r_quantity,
subpl.item_id
FROM po_headers_all subph
INNER JOIN po_lines_all subpl ON subph.po_header_id = subpl.po_header_id
INNER JOIN po_line_locations_all subplla ON subplla.po_header_id = subph.po_header_id
AND subpl.po_line_id = subplla.po_line_id
AND subplla.org_id = subpl.org_id
WHERE to_date(subplla.creation_date) >= to_date(&Roll_back_date, 'DD-MON-RRRR')
GROUP BY subph.attribute1,
subph.currency_code,
subpl.item_id
) quan ON pl.item_id = quan.item_id
-------------------SUBQUERY---------------------------------------
LEFT JOIN (
SELECT mmt.ORGANIZATION_ID,
mmt.INVENTORY_ITEM_ID,
ABS(SUM(mmt.transaction_quantity)) AS annual_Consumption
FROM MTL_MATERIAL_TRANSACTIONS mmt
WHERE mmt.TRANSACTION_ACTION_ID NOT IN (24,30)
AND mmt.TRANSACTION_TYPE_ID IN (33,52)
AND mmt.transaction_date BETWEEN to_date(add_months(&CONS_f_DATE, - 12), 'DD-MON-YYYY')
AND to_date(&CONS_f_DATE, 'DD-MON-YYYY')
AND mmt.parent_transaction_id IS NULL
) mmt ON mmt.ORGANIZATION_ID = MSIB.organization_id --499--579
AND mmt.INVENTORY_ITEM_ID = MSIB.inventory_item_id --4128 --4165
WHERE msib.organization_id IN (
SELECT haou.organization_id
FROM hr_organization_information hoi
JOIN hr_all_organization_units haou ON haou.organization_id = hoi.organization_id
WHERE hoi.org_information1 = 'INV'
AND hoi.org_information2 = 'Y'
AND haou.name LIKE '%HEIS%'
)
AND MSIB.Inventory_Item_Id = NVL(&ITEM, MSIB.Inventory_Item_Id)
AND MSIB.organization_id = nvl(&P_ORGI, MSIB.organization_id)
AND to_date(plla.creation_date) BETWEEN to_date(add_months(&Roll_back_date, - 12), 'DD-MON-YYYY')
AND to_date(&Roll_back_date, 'DD-MON-YYYY')
GROUP BY msib.segment1,
MSIB.inventory_item_id,
msib.description,
MSIB.organization_id,
msib.primary_unit_of_measure,
ph.attribute1,
ph.currency_code;
Here is the query in its simplest form, The main query is working good without the subquery. But when subquery returns null (i.e. no output in the date range) the whole query returns nothing. I want it to display results regardless the subquery results. My guess is something is wrong with the JOIN –
SELECT distinct msib.segment1 Item_Code,
MSIB.inventory_item_id,
MSIB.organization_id ORG_ID,
msib.description Item_Description,
msib.primary_unit_of_measure UOM,
ph.attribute1 Item_Type,
ph.currency_code currency,
max(pl.unit_price) FOB_Value_in_FCY,
max(ph.rate_date),
max(ph.rate) forex_rate,
sum(quan.t_quantity) - sum(r_quantity) finala
FROM mtl_system_items_b MSIB,
PO_HEADERS_ALL ph,
Po_Lines_All pl,
PO_LINE_LOCATIONS_ALL PLLA,
------------SUBQUERY-------------------------------
(select nvl(sum(subplla.quantity),0) t_quantity, nvl(sum(subplla.quantity_received),0) r_quantity ,subpl.item_id
from po_headers_all subph,
po_lines_all subpl,
po_line_locations_all subplla
where subph.po_header_id = subpl.po_header_id
and subplla.po_header_id = subph.po_header_id
and subpl.po_line_id = subplla.po_line_id
and subplla.org_id = subpl.org_id
and to_date(subplla.creation_date) >= to_date(&Roll_back_date,'DD-MON-RRRR')
group by subph.attribute1, subph.currency_code, subpl.item_id
) quan
------------SUBQUERY-------------------------------
WHERE 1=1
and ph.po_header_id = pl.po_header_id
and msib.inventory_item_id (+) = pl.item_id
-----------------joining subquery-------------------
and pl.item_id (+) = quan.item_id
-----------------joining subquery-------------------
and plla.po_header_id = ph.po_header_id
and pl.po_line_id = plla.po_line_id
and plla.org_id = pl.org_id
and msib.organization_id in
(select haou.organization_id
from hr_organization_information hoi,
hr_all_organization_units haou
where haou.organization_id = hoi.organization_id
and hoi.org_information1 = 'INV'
and hoi.org_information2 = 'Y'
and haou.name like '%HEIS%')
and MSIB.Inventory_Item_Id=NVL(&ITEM,MSIB.Inventory_Item_Id)
and MSIB.organization_id = nvl(&P_ORGI, MSIB.organization_id)
AND to_date(plla.creation_date) BETWEEN
to_date(add_months(&Roll_back_date, -12),'DD-MON-YYYY') AND
to_date(&Roll_back_date,'DD-MON-YYYY')
GROUP BY msib.segment1,
MSIB.inventory_item_id,
msib.description,
MSIB.organization_id,
msib.primary_unit_of_measure,
ph.attribute1,
ph.currency_code

Convert SQL Server update set from (with a join) to Oracle

SQL Server table definition:
CREATE TABLE #tmp_pricing
(
contract_nbr integer not null,
pricing_order integer not null,
priced_from_contract_flag char(1) COLLATE DATABASE_DEFAULT not null,
release_nbr integer null,
quantity decimal(25, 6) not null,
price decimal(25, 6) null,
price_future decimal(25, 6) null,
price_basis decimal(25, 6) null,
sum_qty decimal(25, 6) null,
row_nbr integer null,
new_quantity decimal(25, 6) null
)
Oracle global temporary table definition
CREATE GLOBAL TEMPORARY TABLE gtt_cpr_tmp_pricing
(
contract_nbr number not null,
pricing_order number not null,
priced_from_contract_flag char(1) not null,
release_nbr number not null,
quantity number(25,6) not null,
price number(18,6) null,
price_future number(18,6) null,
price_basis number(18,6) null,
sum_qty number(25,6) null,
row_nbr number null,
new_quantity number(25,6) null
)
ON COMMIT DELETE ROWS
tablespace temp
/
SQL Server SQL statement:
UPDATE #tmp_pricing
SET row_nbr = Q.row_nbr
FROM #tmp_pricing
JOIN (SELECT contract_nbr,
pricing_order,
priced_from_contract_flag,
release_nbr,
ROW_NUMBER() OVER (PARTITION BY contract_nbr
ORDER BY contract_nbr,
priced_from_contract_flag,
CASE WHEN pricing_order < 0
THEN 1
ELSE 0
END,
pricing_order
) AS row_nbr
FROM #tmp_pricing
) Q
ON #tmp_pricing.contract_nbr = Q.contract_nbr
AND #tmp_pricing.pricing_order = Q.pricing_order
AND #tmp_pricing.priced_from_contract_flag = Q.priced_from_contract_flag
AND COALESCE(#tmp_pricing.release_nbr, 0) = COALESCE(Q.release_nbr, 0)
Oracle statement (using Merge)
MERGE INTO gtt_cpr_tmp_pricing t
USING (SELECT contract_nbr,
pricing_order,
priced_from_contract_flag,
release_nbr,
ROW_NUMBER() OVER (PARTITION BY contract_nbr
ORDER BY contract_nbr,
priced_from_contract_flag,
CASE WHEN pricing_order < 0
THEN 1
ELSE 0
END,
pricing_order
) AS row_nbr
FROM gtt_cpr_tmp_pricing
)
Q
ON (t.contract_nbr = Q.contract_nbr AND
t.pricing_order = Q.pricing_order AND
t.priced_from_contract_flag = Q.priced_from_contract_flag AND
COALESCE(t.release_nbr, 0) = COALESCE(Q.release_nbr, 0)
)
WHEN MATCHED
THEN UPDATE SET row_nbr = Q.row_nbr;
This is the error I get:
ORA-30926: unable to get a stable set of rows in the source tables
I would like to convert the statement to an update .. set ..where exists
structure but am doing something wrong; here is my (first) attempt:
UPDATE gtt_cpr_tmp_pricing
SET row_nbr = (SELECT contract_nbr,
pricing_order,
priced_from_contract_flag,
release_nbr,
ROW_NUMBER() OVER (PARTITION BY contract_nbr
ORDER BY contract_nbr,
priced_from_contract_flag,
CASE WHEN pricing_order < 0
THEN 1
ELSE 0
END,
pricing_order
) AS row_nbr
FROM gtt_cpr_tmp_pricing ctp
WHERE gtt_cpr_tmp_pricing.contract_nbr = contract_nbr
AND gtt_cpr_tmp_pricing.pricing_order = pricing_order
AND gtt_cpr_tmp_pricing.priced_from_contract_flag = priced_from_contract_flag
AND COALESCE(gtt_cpr_tmp_pricing.release_nbr, 0) = COALESCE(release_nbr, 0)
)
WHERE EXISTS (SELECT 1
FROM gtt_cpr_tmp_pricing
WHERE gtt_cpr_tmp_pricing.contract_nbr = contract_nbr
AND gtt_cpr_tmp_pricing.pricing_order = pricing_order
AND gtt_cpr_tmp_pricing.priced_from_contract_flag = priced_from_contract_flag
AND COALESCE(gtt_cpr_tmp_pricing.release_nbr, 0) = COALESCE(release_nbr, 0)
);
Any assistance would be appreciated.
Murray
When you use inline views in Oracle, columns without an alias reference the tables in the inline view. You need to use a table alias to reference the table in the update clause inside your inline views. Note the price_outer alias and where it's used.
UPDATE gtt_cpr_tmp_pricing price_outer
SET row_nbr = (SELECT contract_nbr,
pricing_order,
priced_from_contract_flag,
release_nbr,
ROW_NUMBER() OVER (PARTITION BY contract_nbr
ORDER BY contract_nbr,
priced_from_contract_flag,
CASE WHEN pricing_order < 0
THEN 1
ELSE 0
END,
pricing_order
) AS row_nbr
FROM gtt_cpr_tmp_pricing ctp
WHERE price_outer.contract_nbr = contract_nbr
AND price_outer.pricing_order = pricing_order
AND price_outer.priced_from_contract_flag = priced_from_contract_flag
AND COALESCE(price_outer.release_nbr, 0) = COALESCE(release_nbr, 0)
)
WHERE EXISTS (SELECT 1
FROM gtt_cpr_tmp_pricing
WHERE price_outer.contract_nbr = contract_nbr
AND price_outer.pricing_order = pricing_order
AND price_outer.priced_from_contract_flag = priced_from_contract_flag
AND COALESCE(price_outer.release_nbr, 0) = COALESCE(release_nbr, 0)
);

How to use 'EXIST' in a simple oracle query

I have a table called ‘MainTable’ with following data
Another table called ‘ChildTable’ with following data (foreighn key Number)
Now I want to fetch those records from ‘ChildTable’ if there exists at least one ‘S’ status.
But if any other record for this number id ‘R’ then I don’t want to fetch it
Something like this-
I tried following
Select m.Number, c.Status from MainTable m, ChildTable c
where EXISTS (SELECT NULL
FROM ChildTable c2
WHERE c2.status =’S’ and c2.status <> ‘R’
AND c2.number = m.number)
But here I am getting record having ‘R’ status also, what I am doing wrong?
You can try something like this
select num, status
from
(select id, num, status,
sum(decode(status, 'R', 1, 0)) over (partition by num) Rs,
sum(decode(status, 'S', 1, 0)) over (partition by num) Ss
from child_table) t
where t.Rs = 0 and t.Ss >= 1
-- and status = 'S'
Here is a sqlfiddle demo
The child records with 'R' might be associated with a maintable record that also has another child record with status 'S' -- that is what your query is asking for.
Select
m.Number,
c.Status
from MainTable m
join ChildTable c on c.number = m.number
where EXISTS (
SELECT NULL
FROM ChildTable c2
WHERE c2.status =’S’
AND c2.number = m.number) and
NOT EXISTS (
SELECT NULL
FROM ChildTable c2
WHERE c2.status =’R’
AND c2.number = m.number)
WITH ChildrenWithS AS (
SELECT Number
FROM ChildTable
WHERE Status = 'S'
)
,ChildrenWithR AS (
SELECT Number
FROM ChildTable
WHERE Status = 'R'
)
SELECT MaintTable.Number
,ChildTable.Status
FROM MainTable
INNER JOIN ChildTable
ON MainTable.Number = ChildTable.Number
WHERE MainTable.Number IN (SELECT Number FROM ChildrenWithS)
AND MainTable.Number NOT IN (SELECT Number FROM ChildrenWithR)

CROSS APPLY too slow for running total - TSQL

Please see my code below as it is running too slowly with the CROSS APPLY.
How can I remove the CROSS APPLY and add something else that will run faster?
Please note I am using SQL Server 2008 R2.
;WITH MyCTE AS
(
SELECT
R.NetWinCURRENCYValue AS NetWin
,dD.[Date] AS TheDay
FROM
dimPlayer AS P
JOIN
dbo.factRevenue AS R ON P.playerKey = R.playerKey
JOIN
dbo.vw_Date AS dD ON Dd.dateKey = R.dateKey
WHERE
P.CustomerID = 12345)
SELECT
A.TheDay AS [Date]
,ISNULL(A.NetWin, 0) AS NetWin
,rt.runningTotal AS CumulativeNetWin
FROM MyCTE AS A
CROSS APPLY (SELECT SUM(NetWin) AS runningTotal
FROM MyCTE WHERE TheDay <= A.TheDay) AS rt
ORDER BY A.TheDay
CREATE TABLE #temp (NetWin money, TheDay datetime)
insert into #temp
SELECT
R.NetWinCURRENCYValue AS NetWin
,dD.[Date] AS TheDay
FROM
dimPlayer AS P
JOIN
dbo.factRevenue AS R ON P.playerKey = R.playerKey
JOIN
dbo.vw_Date AS dD ON Dd.dateKey = R.dateKey
WHERE
P.CustomerID = 12345;
SELECT
A.TheDay AS [Date]
,ISNULL(A.NetWin, 0) AS NetWin
,SUM(B.NetWin) AS CumulativeNetWin
FROM #temp AS A
JOIN #temp AS B
ON A.TheDay >= B.TheDay
GROUP BY A.TheDay, ISNULL(A.NetWin, 0);
Here https://stackoverflow.com/a/13744550/613130 it's suggested to use recursive CTE.
;WITH MyCTE AS
(
SELECT
R.NetWinCURRENCYValue AS NetWin
,dD.[Date] AS TheDay
,ROW_NUMBER() OVER (ORDER BY dD.[Date]) AS RN
FROM dimPlayer AS P
JOIN dbo.factRevenue AS R ON P.playerKey = R.playerKey
JOIN dbo.vw_Date AS dD ON Dd.dateKey = R.dateKey
WHERE P.CustomerID = 12345
)
, MyCTERec AS
(
SELECT C.TheDay AS [Date]
,ISNULL(C.NetWin, 0) AS NetWin
,ISNULL(C.NetWin, 0) AS CumulativeNetWin
,C.RN
FROM MyCTE AS C
WHERE C.RN = 1
UNION ALL
SELECT C.TheDay AS [Date]
,ISNULL(C.NetWin, 0) AS NetWin
,P.CumulativeNetWin + ISNULL(C.NetWin, 0) AS CumulativeNetWin
,C.RN
FROM MyCTERec P
INNER JOIN MyCTE AS C ON C.RN = P.RN + 1
)
SELECT *
FROM MyCTERec
ORDER BY RN
OPTION (MAXRECURSION 0)
Note that this query will work if you have 1 record == 1 day! If you have multiple records in a day, the results will be different from the other query.
As I said here, if you want really fast calculation, put it into temporary table with sequential primary key and then calculate rolling total:
create table #Temp (
ID bigint identity(1, 1) primary key,
[Date] date,
NetWin decimal(29, 10)
)
insert into #Temp ([Date], NetWin)
select
dD.[Date],
sum(R.NetWinCURRENCYValue) as NetWin,
from dbo.dimPlayer as P
inner join dbo.factRevenue as R on P.playerKey = R.playerKey
inner join dbo.vw_Date as dD on Dd.dateKey = R.dateKey
where P.CustomerID = 12345
group by dD.[Date]
order by dD.[Date]
;with cte as (
select T.ID, T.[Date], T.NetWin, T.NetWin as CumulativeNetWin
from #Temp as T
where T.ID = 1
union all
select T.ID, T.[Date], T.NetWin, T.NetWin + C.CumulativeNetWin as CumulativeNetWin
from cte as C
inner join #Temp as T on T.ID = C.ID + 1
)
select C.[Date], C.NetWin, C.CumulativeNetWin
from cte as C
order by C.[Date]
I assume that you could have duplicates dates in the input, but don't want duplicates in the output, so I grouped data before puting it into the table.

Oracle update Query does not work

I have an ORACLE query which does not work for this query.
UPDATE emp a set a.Enq_Status = 'PROGRESS'
where exists (select * from emp a, Data b
WHERE a.SA_Enq_Status is NULL
and a.EQ_Status = 'ACTIVATED'
and a.Activation_Return_Code = 0
and a.Alert_Code > 0
and a.User_Id = b.User_Id
and (b.Is_Associate is NULL or b.Is_Associate = 0)
and (b.Stk_Schd is NULL)
and (b.Stk_Dis_Amt is NULL)
);
My Problem is I want to update mutiple records in the table emp (A) to status to 'PROGRESS'.But when executing this query all records in a.Enq_status is changes.Please help me in this.Updation is not correct.Please help me in this
You have specified table emp both in the update query and the subquery too, Oracle will treat these as seperate tables.
You need a correlated subquery:
UPDATE emp a
set a.Enq_Status = 'PROGRESS'
where exists (select 'X'
from Data b
WHERE a.SA_Enq_Status is NULL
and a.EQ_Status = 'ACTIVATED'
and a.Activation_Return_Code = 0
and a.Alert_Code > 0
and a.User_Id = b.User_Id
and (b.Is_Associate is NULL or b.Is_Associate = 0)
and (b.Stk_Schd is NULL)
and (b.Stk_Dis_Amt is NULL));
You could probably just update the emp table without the need for the subquery though if you link to the Data table in the where clause...
Your update statement will update all the records in emp table because you don't specify the records to update. If your sub-query returns at least one row, the all the emp records will be updated. If it returns no rows, then none of the records will be updated.
Change your update like this:
UPDATE emp SET Enq_Status = 'PROGRESS'
WHERE id in
(SELECT a.id
FROM emp a, Data b
WHERE a.SA_Enq_Status is NULL and a.EQ_Status = 'ACTIVATED'
and a.Activation_Return_Code = 0 and a.Alert_Code > 0
and a.User_Id = b.User_Id and (b.Is_Associate is NULL or b.Is_Associate = 0)
and (b.Stk_Schd is NULL)and (b.Stk_Dis_Amt is NULL)
);
Try:
UPDATE emp a
SET a.enq_status = 'PROGRESS'
WHERE a.sa_enq_status IS NULL
AND a.eq_status = 'ACTIVATED'
AND a.activation_return_code = 0
AND a.alert_code > 0
AND EXISTS
(SELECT 'X'
FROM data b
WHERE a.user_id = b.user_id
AND ( b.is_associate IS NULL OR b.is_associate = 0 )
AND b.stk_schd IS NULL
AND b.stk_dis_amt IS NULL);

Resources