Related
I am trying to create a CTE to use the same in Merge statement in Oracle, but facing error so please have a look and help me out, earlier we were using subquery instead CTE but to enhance the response time of query I am trying CTE so please suggest me another approach to enhance the response time of query. Curious to know whether oracle supports CTE and Merge statement together as I did in below code.
With TRANS_HIST
As
(Select
NUMERO_DE_CUENTA,
TRANS_DATETIME,
Lag(TRANS_DATETIME, 1)
over
(
ORDER BY NUMERO_DE_CUENTA,TRANS_DATETIME) lag_trans_datetime
FROM db_fraud_bpd.tbl_event_new_transaction_h
)
MERGE
INTO DB_FRAUD_BPD.TBL_RT_FEATURES_TEMP t1
USING
(
SELECT
RTTEMP.ACCOUNT_NUMBER,
RTTEMP.TRANS_DATETIME,
CASE WHEN STDDEV(TRANS_HIST.TRANS_DATETIME - TRANS_HIST.lag_trans_datetime) = 0 THEN NULL
WHEN ROUND(( ( (RTTEMP.TRANS_DATETIME - Max(TRANS_HIST.TRANS_DATETIME)) - Avg(TRANS_HIST.TRANS_DATETIME - TRANS_HIST.lag_trans_datetime)) / STDDEV(TRANS_HIST.TRANS_DATETIME -TRANS_HIST.lag_trans_datetime)),3) >999999999999999 THEN 999999999999999
WHEN ROUND(( ( (RTTEMP.TRANS_DATETIME - Max(TRANS_HIST.TRANS_DATETIME)) - Avg(TRANS_HIST.TRANS_DATETIME - TRANS_HIST.lag_trans_datetime)) / STDDEV(TRANS_HIST.TRANS_DATETIME -TRANS_HIST.lag_trans_datetime)),3) <-99999999999999 THEN -99999999999999
ELSE ROUND(( ( (RTTEMP.TRANS_DATETIME - Max(TRANS_HIST.TRANS_DATETIME)) - Avg(TRANS_HIST.TRANS_DATETIME - TRANS_HIST.lag_trans_datetime)) / STDDEV(TRANS_HIST.TRANS_DATETIME -TRANS_HIST.lag_trans_datetime)),3)
END AS TIME_DELTA_ZSCORE_PAST_90_DAYS
FROM TRANS_HIST
right outer join
db_fraud_bpd.tbl_rt_features_temp RTTEMP
ON Cast(RTTEMP.account_number AS INTEGER) = Cast(TRANS_HIST.NUMERO_DE_CUENTA AS INTEGER)
WHERE
(
TRANS_HIST.TRANS_DATETIME < RTTEMP.TRANS_DATETIME
AND TRANS_HIST.TRANS_DATETIME >= (RTTEMP.TRANS_DATETIME-90)
)
or TRANS_HIST.TRANS_DATETIME IS NULL
GROUP BY
RTTEMP.account_number,
RTTEMP.TRANS_DATETIME
)TEMP
ON (t1.TRANS_DATETIME=TEMP.TRANS_DATETIME AND t1.ACCOUNT_NUMBER=TEMP.ACCOUNT_NUMBER)
WHEN MATCHED
THEN UPDATE
SET t1.TIME_DELTA_ZSCORE_PAST_90_DAYS = TEMP.TIME_DELTA_ZSCORE_PAST_90_DAYS
You may use CTE in the merge statement, but in the rigth position in the merge subquery.
See example below
merge into tab
using (with t as (
select 1 id, 'x' x from dual union all
select 2 id, 'y' x from dual)
select * from t) b
on (tab.id = b.id)
when matched then
update set tab.x = b.x
when not matched then
insert (id, x)
values (b.id, b.x);
Don't use TRANS_HIST as a CTE, but as a subquery.
MERGE INTO DB_FRAUD_BPD.TBL_RT_FEATURES_TEMP t1
USING ( SELECT RTTEMP.ACCOUNT_NUMBER,
RTTEMP.TRANS_DATETIME,
CASE
WHEN STDDEV (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime) =
0
THEN
NULL
WHEN ROUND (
( ( ( RTTEMP.TRANS_DATETIME
- MAX (TRANS_HIST.TRANS_DATETIME))
- AVG (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime))
/ STDDEV (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime)),
3) >
999999999999999
THEN
999999999999999
WHEN ROUND (
( ( ( RTTEMP.TRANS_DATETIME
- MAX (TRANS_HIST.TRANS_DATETIME))
- AVG (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime))
/ STDDEV (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime)),
3) <
-99999999999999
THEN
-99999999999999
ELSE
ROUND (
( ( ( RTTEMP.TRANS_DATETIME
- MAX (TRANS_HIST.TRANS_DATETIME))
- AVG (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime))
/ STDDEV (
TRANS_HIST.TRANS_DATETIME
- TRANS_HIST.lag_trans_datetime)),
3)
END AS TIME_DELTA_ZSCORE_PAST_90_DAYS
FROM (SELECT NUMERO_DE_CUENTA,
TRANS_DATETIME,
LAG (TRANS_DATETIME, 1)
OVER (
ORDER BY NUMERO_DE_CUENTA, TRANS_DATETIME) lag_trans_datetime
FROM db_fraud_bpd.tbl_event_new_transaction_h)
TRANS_HIST
RIGHT OUTER JOIN db_fraud_bpd.tbl_rt_features_temp RTTEMP
ON CAST (RTTEMP.account_number AS INTEGER) =
CAST (TRANS_HIST.NUMERO_DE_CUENTA AS INTEGER)
WHERE ( TRANS_HIST.TRANS_DATETIME < RTTEMP.TRANS_DATETIME
AND TRANS_HIST.TRANS_DATETIME >=
(RTTEMP.TRANS_DATETIME - 90))
OR TRANS_HIST.TRANS_DATETIME IS NULL
GROUP BY RTTEMP.account_number, RTTEMP.TRANS_DATETIME) TEMP
ON ( t1.TRANS_DATETIME = TEMP.TRANS_DATETIME
AND t1.ACCOUNT_NUMBER = TEMP.ACCOUNT_NUMBER)
WHEN MATCHED
THEN
UPDATE SET
t1.TIME_DELTA_ZSCORE_PAST_90_DAYS = TEMP.TIME_DELTA_ZSCORE_PAST_90_DAYS
I created a table a DAX Studio and want to repeat all the rows (with all the columns) in a new table multiple times; to my choosing.
//create temp table of Historic Facilities for all annual groups 1 to 3
TABLE HistFac =
ADDCOLUMNS ( FacSchHist,
"Rank", RANKX ( FacSchHist, [WtAvg] ),
"Annual Group", (RANKX ( FacSchHist, [WtAvg] ) - FLOOR((RANKX ( FacSchHist, [WtAvg] ) - 1) /3 * 3,3)))
EVALUATE
NonHistFac
ORDER BY [Annual Group],
[WtAvg] DESC
I want the maintain the original order in the repeated list. There are obviously many ways to construct a table (see code above); however, how does one repeat the list of rows?
Thanks you for any suggestions.
Try to remove the filters that are affecting the measure inside RANKX because of the context transition coming from the table provide in the first argument of GENERATE
DEFINE
TABLE HistFac =
GENERATE (
{ 1, 2, 3 },
ADDCOLUMNS (
ADDCOLUMNS (
FacSchHist,
"#Rank",
RANKX (
FacSchHist,
CALCULATE ( [WtAvg], REMOVEFILTERS ( TableSupliedInTheFirstArgument ) )
)
),
"Annual Group",
[#Rank]
- FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
)
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC
Or simply use variables to compute in a different filter context.
DEFINE
TABLE HistFac =
VAR RankedTable =
ADDCOLUMNS ( FacSchHist, "#Rank", RANKX ( FacSchHist, [WtAvg] ) )
VAR SomeCalculationOnRankedTable =
ADDCOLUMNS (
RankedTable,
"Annual Group",
[#Rank]
- FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
RETURN
GENERATE ( { 1, 2, 3 }, SomeCalculationOnRankedTable )
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC
You can use GENERATE for repeating the rows:
DEFINE
TABLE HistFac =
GENERATE (
{ 1, 2, 3 },
ADDCOLUMNS (
FacSchHist,
"Rank", RANKX ( FacSchHist, [WtAvg] ),
"Annual Group",
(
RANKX ( FacSchHist, [WtAvg] )
- FLOOR ( ( RANKX ( FacSchHist, [WtAvg] ) - 1 ) / 3 * 3, 3 )
)
)
)
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC
A better way to write this code will be to use nested ADDCOLUMNS:
DEFINE
TABLE HistFac =
GENERATE (
{ 1, 2, 3 },
ADDCOLUMNS (
ADDCOLUMNS ( FacSchHist, "#Rank", RANKX ( FacSchHist, [WtAvg] ) ),
"Annual Group",
[#Rank]
- FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
)
EVALUATE
NonHistFac
ORDER BY
[Annual Group],
[WtAvg] DESC
AntrikshSharma - I will give those a try now , appreciate your guidance.
Okay, the code worked fine; but uncovered a problem. After the initial ranking of the list, and before the replication - I do not want to continue ranking.
In other words, I want the initial ranked-list to be reproduced 3x without any further ranking; just have each duplicated occurrence appear after the initial list in the exact order.
If the initial list was 12345, then 12345,12345,12345 - thank you for the more efficient code as well.
AntrikshSharma, your comment and code, "Or simply use variables to compute in a different filter context" is genius. The code performed as expected. The problem I'm experiencing is with the UNION of the two tables "NonHistFac" and "HistFac". I will provide an image to explain then the most current code.
15yr cycle of Hist & NonHist Facilities
The image shows the goal. combine the NonHistFac (all surveyed every 5yrs) with the HistFac (all surveyed every 3yrs). The original ranking must be maintained (this is currently met.)
Here is the problem. The numbers within the image are the Values as produced by the GENERATE function. When the tables are combined and the NonHistFac are mixed with the HistFac, they are not evenly distributed throughout the 1 to 5 Values.
What appears in Values 4 and 5 is obviously the remaining HistFac. I need to have the entire combination distributed from 1 to 5; or as shown, over the 15 year cycle.
Thank you.
// produce non-historic table with additional columns and replicate all rows 3x
TABLE NonHistFac =
VAR NonHistRankedTable =
ADDCOLUMNS ( FacSchNonHist, "#Rank", RANKX ( FacSchNonHist, [WtAvg] ) )
VAR NonHistAnnualizedRankedTable =
ADDCOLUMNS (
NonHistRankedTable,
"Annual Group",
[#Rank] - FLOOR ( ( [#Rank] - 1 ) / 5 * 5, 5 )
)
RETURN
GENERATE ( { 1, 2, 3 }, NonHistAnnualizedRankedTable )
// from the FLOOR & GENERATE functions, 5 x 3 = 15 (this is a 15 year cycle)
//produce historic facility table with additional columns and replicate all rows 5x
TABLE HistFac =
VAR HistRankedTable =
ADDCOLUMNS ( FacSchHist, "#Rank", RANKX ( FacSchHist, [WtAvg] ) )
VAR HistAnnualizedRankedTable =
ADDCOLUMNS (
HistRankedTable,
"Annual Group",
[#Rank] - FLOOR ( ( [#Rank] - 1 ) / 3 * 3, 3 )
)
RETURN
GENERATE ( { 1, 2, 3, 4, 5 }, HistAnnualizedRankedTable )
// from the FLOOR & GENERATE functions, 3 x 5 = 15 (this is a 15 year cycle)
// combine the tables NonHistFac & HistFac to create one-table representing a 15 yr cycle
VAR FacSchUnion =
UNION(
NonHistFac,
HistFac
)
VAR FacSch15yr =
DISTINCT(FacSchUnion)
EVALUATE
FacSch15yr
ORDER BY [Value],
[Annual Group],
[WtAvg] DESC
I want to select duplicate data in column 'egno' and not duplicate data in 'dsver'.
My source MySQL query is:
select * from test
where egno in (
select egno
from test
group by egno
having count (*) >1
)
group by dsver
having count (*) = 1
But it doesn't work on Oracle. So I wrote a new query:
select * from test
where egno in (
select egno
from test
group by egno
having count (*) >1
)
and dsver in (
select dsver
from test
group by dsver
having count (*) = 1
)
I think it will use more resources on the server. I need some suggestions on this query.
Use the COUNT() analytic function:
SELECT *
FROM (
SELECT t.*,
COUNT(*) OVER ( PARTITION BY egno ) AS num_egno,
COUNT(*) OVER ( PARTITION BY dsver ) AS num_dsver
FROM test t
)
WHERE num_egno > 1
AND num_dsver = 1;
I have a following query and it takes 12 hours to execute in HUE. I would like to increase the performance of the query. Let me know what changes I can implement in the query to increase the performance in HUE environment
SELECT ordernum,
Min(distance) mindist,
Min(CASE
WHEN type_name = 'T'
OR ( type_name = 'I'
AND item LIKE '%D%' ) THEN distance
ELSE 9999999
END) min_t,
Min(CASE
WHEN type_name = 'A' THEN distance
ELSE 9999999
END) min_a
FROM (SELECT a.ordernum,
b.id,
b.type_name,
b.item,
Round(Least(Sqrt(Pow(b.sty-a.nrthng, 2)
+ Pow(b.stx-a.estng, 2)),
Sqrt(Pow(b.endy-a.nrthng, 2)
+ Pow(b.endx-a.estng, 2))))
distance
FROM temp_b a,
min_b1 b
WHERE ( ( b.stx BETWEEN ( a.estng - 1000 ) AND ( a.estng + 1000 )
AND b.sty BETWEEN ( a.nrthng - 1000 ) AND
( a.nthing + 1000 ) )
OR ( b.endx BETWEEN ( a.estng - 1000 ) AND ( a.esng + 1000 )
AND b.endy BETWEEN ( a.nrthng - 1000 ) AND
( a.nrthng + 1000 ) ) )) a
GROUP BY ordernum
My concers are about your query join condition.
As I see, you have tables a and b. Are there any key fields so tables could be matched? I mean, field f1 from the table a has the same meaning as field f2 from table b so they could be joined.
You could also create temporary table containing information from both tables to remove overhead for network communication and data transfer as I believe your hadoop cluster contains more than single node.
So, I have this query that's just making me go crazy. For some crazy reason, the query runs and brings the desired output on PLSQL Developer, but on SQL Developer it doesn't! As far as I know, the exact same query should work on both, not just one or the other. Not everybody at my team has PLSQL Dev, so it has to work on both. This query also shows different behaviour on my BI Application. Has anyone seen this crazy behaviour before?
Here's the query:
with t1 as (
SELECT
case when CLG_STATUS.NM_STATUS in ('1 - ATIVO','5 - BLOQUEADO','7 - AGUARDANDO AUTENTICAÇÃO') then 'LG Club Member'
else 'Non Member'
end membership,
Round(
Round(SUM(NVL(CASE WHEN CLG_VENDA.CD_TP_VENDA = 'D' THEN -1*CLG_VENDA.QTD_VENDA ELSE CLG_VENDA.QTD_VENDA END,0)), 1)
/
Count(distinct CLG_PARTICIPANTE.ID)
, 1) as average_sales ,
Round(
SUM(NVL(CASE WHEN CLG_VENDA.CD_TP_VENDA = 'D' THEN -1*CLG_VENDA.QTD_VENDA ELSE CLG_VENDA.QTD_VENDA END,0))
, 1) as sellout,
Count(distinct CLG_PARTICIPANTE.ID)
as "qty members"
FROM
CLG_VENDA_PONTO,
CLG_PARTICIPANTE,
CLG_STATUS,
CLG_VENDA,
CLG_CARGO CLG_CARGO_VENDA,
CLG_CANAL CLG_CANAL_VENDA,
CLG_REDE CLG_REDE_VENDA,
CLG_PRODUTO,
CLG_TP_MOVIMENTO,
DIM_PERIOD_DAY PERIOD_VENDA_DATA,
CLG_LOJA CLG_LOJA_VENDA
WHERE
( CLG_VENDA_PONTO.ID_VENDA=CLG_VENDA.ID(+) )
AND ( CLG_VENDA_PONTO.ID_PROD=CLG_PRODUTO.ID(+) )
AND ( CLG_VENDA_PONTO.ID_CARGO=CLG_CARGO_VENDA.ID )
AND ( CLG_LOJA_VENDA.ID=CLG_VENDA_PONTO.ID_LOJA )
AND ( CLG_REDE_VENDA.ID=CLG_LOJA_VENDA.ID_REDE )
AND ( CLG_CANAL_VENDA.ID=CLG_VENDA_PONTO.ID_CANAL )
AND ( CLG_PARTICIPANTE.ID_LOJA=CLG_LOJA_VENDA.ID )
AND ( CLG_LOJA_VENDA.ID_REDE=CLG_REDE_VENDA.ID )
AND ( CLG_PARTICIPANTE.ID=CLG_VENDA_PONTO.ID_PARTCPTE )
AND ( CLG_VENDA_PONTO.ID_TP_MOVIMENTO=CLG_TP_MOVIMENTO.ID )
AND ( CLG_STATUS.ID=CLG_PARTICIPANTE.ID_STATUS )
AND ( CLG_VENDA_PONTO.DATA_VENDA=PERIOD_VENDA_DATA.YYYYMMDD )
AND ( CLG_CARGO_VENDA.NM_CARGO = '5 - VENDEDOR' OR CLG_VENDA.ID_CARGO = 8 )
AND
(
CLG_PRODUTO.NM_PRODUTO NOT IN ( 'M4338 - FRETE','R39745 - FRETE SOBRE VENDAS' )
AND
CLG_TP_MOVIMENTO.NM_MOVIMENTO IN ( '1 - VENDA','3 - DEVOLUCAO' )
AND
CLG_REDE_VENDA.NM_REDE = '21540901 - RABELO'
AND
PERIOD_VENDA_DATA.YYYYMMDD_DATE BETWEEN to_date('01-01-2013', 'DD-MM-YYYY') AND to_date('31-12-2013', 'DD-MM-YYYY')
AND
CLG_CANAL_VENDA.NM_CANAL IN ('1 - VAREJO')
AND
CLG_PRODUTO.FG_MAPEADO IN ( 'SIM' )
)
GROUP BY
case when CLG_STATUS.NM_STATUS in ('1 - ATIVO','5 - BLOQUEADO','7 - AGUARDANDO AUTENTICAÇÃO') then 'LG Club Member'
else 'Non Member'
end
), t2 as (
SELECT
case when CLG_STATUS.NM_STATUS in ('1 - ATIVO','5 - BLOQUEADO','7 - AGUARDANDO AUTENTICAÇÃO') then 'LG Club Member'
else 'Non Member'
end membership,
Round(
Round(SUM(NVL(CASE WHEN CLG_VENDA.CD_TP_VENDA = 'D' THEN -1*CLG_VENDA.QTD_VENDA ELSE CLG_VENDA.QTD_VENDA END,0)), 1)
/
Count(distinct CLG_PARTICIPANTE.ID)
, 1) as average_sales ,
Round(
SUM(NVL(CASE WHEN CLG_VENDA.CD_TP_VENDA = 'D' THEN -1*CLG_VENDA.QTD_VENDA ELSE CLG_VENDA.QTD_VENDA END,0))
, 1) as sellout,
Count(distinct CLG_PARTICIPANTE.ID)
as "qty members"
FROM
CLG_VENDA_PONTO,
CLG_PARTICIPANTE,
CLG_STATUS,
CLG_VENDA,
CLG_CARGO CLG_CARGO_VENDA,
CLG_CANAL CLG_CANAL_VENDA,
CLG_REDE CLG_REDE_VENDA,
CLG_PRODUTO,
CLG_TP_MOVIMENTO,
DIM_PERIOD_DAY PERIOD_VENDA_DATA,
CLG_LOJA CLG_LOJA_VENDA
WHERE
( CLG_VENDA_PONTO.ID_VENDA=CLG_VENDA.ID(+) )
AND ( CLG_VENDA_PONTO.ID_PROD=CLG_PRODUTO.ID(+) )
AND ( CLG_VENDA_PONTO.ID_CARGO=CLG_CARGO_VENDA.ID )
AND ( CLG_LOJA_VENDA.ID=CLG_VENDA_PONTO.ID_LOJA )
AND ( CLG_REDE_VENDA.ID=CLG_LOJA_VENDA.ID_REDE )
AND ( CLG_CANAL_VENDA.ID=CLG_VENDA_PONTO.ID_CANAL )
AND ( CLG_PARTICIPANTE.ID_LOJA=CLG_LOJA_VENDA.ID )
AND ( CLG_LOJA_VENDA.ID_REDE=CLG_REDE_VENDA.ID )
AND ( CLG_PARTICIPANTE.ID=CLG_VENDA_PONTO.ID_PARTCPTE )
AND ( CLG_VENDA_PONTO.ID_TP_MOVIMENTO=CLG_TP_MOVIMENTO.ID )
AND ( CLG_STATUS.ID=CLG_PARTICIPANTE.ID_STATUS )
AND ( CLG_VENDA_PONTO.DATA_VENDA=PERIOD_VENDA_DATA.YYYYMMDD )
AND ( CLG_CARGO_VENDA.NM_CARGO = '5 - VENDEDOR' OR CLG_VENDA.ID_CARGO = 8 )
AND
(
CLG_PRODUTO.NM_PRODUTO NOT IN ( 'M4338 - FRETE','R39745 - FRETE SOBRE VENDAS' )
AND
CLG_TP_MOVIMENTO.NM_MOVIMENTO IN ( '1 - VENDA','3 - DEVOLUCAO' )
AND
CLG_REDE_VENDA.NM_REDE = '21540901 - RABELO'
AND
PERIOD_VENDA_DATA.YYYYMMDD_DATE BETWEEN add_months(to_date('01-01-2013', 'DD-MM-YYYY'), -12) AND add_months(to_date('31-12-2013', 'DD-MM-YYYY'), -12)
AND
CLG_CANAL_VENDA.NM_CANAL IN ('1 - VAREJO')
AND
CLG_PRODUTO.FG_MAPEADO IN ( 'SIM' )
)
GROUP BY
case when CLG_STATUS.NM_STATUS in ('1 - ATIVO','5 - BLOQUEADO','7 - AGUARDANDO AUTENTICAÇÃO') then 'LG Club Member'
else 'Non Member'
end
)
select t1.*, coalesce((t1.average_sales - t2.average_sales) / t2.average_sales, 0) as variation
from t1 join t2 on t1.membership = t2.membership
On SQL Developer it displays this:
ORA-00928: missing SELECT keyword
00928. 00000 - "missing SELECT keyword"
I'm totally at a loss here. How can a query parse at one tool and not the other ? I tried searching around the net but to no avail.
Thanks in advance!
It might be the line,
/
SQL Plus uses / by itself to mark the end of a sql query, and SQL Developer most likely follows. However, the preceding whitespace may change the meaning, so this may not be the problem.
To test this hypothesis move the / to the preceding line. Change
Round(SUM(NVL(CASE WHEN CLG_VENDA.CD_TP_VENDA = 'D' THEN -1*CLG_VENDA.QTD_VENDA ELSE CLG_VENDA.QTD_VENDA END,0)), 1)
/
Count(distinct CLG_PARTICIPANTE.ID)
To
Round(SUM(NVL(CASE WHEN CLG_VENDA.CD_TP_VENDA = 'D' THEN -1*CLG_VENDA.QTD_VENDA ELSE CLG_VENDA.QTD_VENDA END,0)), 1) /
Count(distinct CLG_PARTICIPANTE.ID)
If that is the problem, then it is a matter of reformatting to something that works for you that doesn't leave / on a line by itself.