Convert SQL Server CTE into Oracle CTE - oracle

Here is the SQL Server CTE, trying to convert to Oracle CTE or regular oracle query..
;with cte as
(Select AC, M, Y, D, E, F, CD
from tblA
WHere
(Y = YEAR(GETDATE()) and M = Month(dateadd(month, -1, GETDATE())))
),
cte2 as
(Select A.AC,Max(A.Y)as Y, Max(A.M) as M, Max(A.CD) as CD
from tbl A
Inner join cte B on B.AC = A.AC
WHere A.CD is Not Null and B.CD is Null
Group by A.AC)
, cte3 as
(Select C.AC, C.Y, C.M, C.D, C.E, C.F, C.CD
from tblA C
Inner join cte2 D on C.AC = D.AC and C.Y= D.Y and C.M = D.M and
D.CD = C.CD
)
select * from cte
union
select * from cte3;

Assuming you didn't have the m and y columns reversed on purpose in your cte/cte3 select lists, I think you could rewrite your query as:
with cte1 as (select a.ac,
a.m,
a.y,
a.d,
a.e,
a.f,
a.cd,
max(case when a.cd is not null and b.cd is not null then a.y end) over (partition by a.ac) max_y,
max(case when a.cd is not null and b.cd is not null then a.m end) over (partition by a.ac) max_m,
max(case when a.cd is not null and b.cd is not null then a.cd end) over (partition by a.ac) max_cd
from tbla a
left outer join tblb b on (a.ac = b.ac))
select ac,
m,
y,
d,
e,
f,
cd
from cte1
where (y = to_char(sysdate, 'yyyy')
and m = to_char(add_months(sysdate, -1), 'mm'))
or (y = max_y
and m = max_m
and cd = max_cd);
You haven't provided any sample data, so I can't test, but it would be worth converting the date functions to their SQL Server equivalents and testing to make sure the data returned is the same.
This way, you're not querying the same table 3 times, which should improve the performance some.

Related

how to filter out null value then compare in oracle

I tried this, and it works,
SELECT name
FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
)
WHERE LENGTH >= ALL
(SELECT LENGTH FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
)
)
but my final code would be like this:
SELECT a.name,
a.length
FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
) a,
geo_river b,
encompasses c
WHERE a.length >= ALL
(SELECT a2.LENGTH
FROM
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL
) a2
)
AND a.name = b.river
AND b.country = c.country
AND c.continent = 'America'
this is really complicated.
Is there an easy way to let
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL)
be river, so I don't need to use this
(SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL)
two times.
If you want to simplify your code writing, you can use WITH:
with viewA as (SELECT name,LENGTH FROM river WHERE LENGTH IS NOT NULL )
SELECT a.name,
a.length
FROM
viewA a,
geo_river b,
encompasses c
WHERE a.length >= ALL
(SELECT a2.LENGTH
FROM
viewA a2
)
AND a.name = b.river
AND b.country = c.country
AND c.continent = 'America'
Using a single table scan:
SELECT name,
length
FROM (
SELECT name,
length,
RANK() OVER ( ORDER BY length DESC ) AS rnk
FROM river
)
WHERE rnk = 1;
So your code would then be:
SELECT a.name,
a.length
FROM (
SELECT name,
length
FROM (
SELECT name,
length,
RANK() OVER ( ORDER BY length DESC ) AS rnk
FROM river
)
WHERE rnk = 1
) a
INNER JOIN
geo_river b
ON ( a.name = b.river )
INNER JOIN
encompasses c
ON ( b.country = c.country )
WHERE c.continent = 'America';
I don't think you need to filter out null lengths as they won't show up if you subset on length (i.e. when comparing NULL values without using the NVL function the comparison will always evaluate to false and not show the row). So something simple such as:
Select a.name, a.length
from river a, geo_river b, encompasses c
WHERE a.length > 0
AND a.name = b.river
AND b.country = c.country
AND c.continent = 'America'
;
Will do the trick

BUG: ORA_00913 Oracle Error - Too many values

The below code is in stored procedure, and they told me to convert it into nested loops and try running it.
insert into PRICEVIEW_RATE_PLAN_PROC (
SSR_CODE
,CORRIDOR_PLAN_ID
,CORRIDOR_PLAN_DESCRIPTION
,USAGE_TYPE
,PRODUCT
,JURISDICTION
,PROVIDER
,RATE_PERIOD
,FLAGFALL
,RATE
,RATEBAND
,NUMSECS
,BAND_RATE
,ACTIVE_DT
,INACTIVE_DT
)
select /*+ use_hash(rate_usage_overrides,corridor_plan_id_values,product_elements,descriptions,jurisdictions,rate_usage_bands_overrides) */
distinct decode(a.corridor_plan_id, 0, '''', (
select c.short_display
from corridor_plan_id_values c
where a.corridor_plan_id = c.corridor_plan_id
)) as SSR_CODE
,a.corridor_plan_id as CORRIDOR_PLAN_ID
,decode(a.corridor_plan_id, 0, '''', (
select d.display_value
from corridor_plan_id_values d
where a.corridor_plan_id = d.corridor_plan_id
)) as CORRIDOR_PLAN_DESCRIPTION
,decode(a.type_id_usg, 0, '''', (
select f.description_text
from usage_types e
,descriptions f
where a.type_id_usg = e.type_id_usg
and e.description_code = f.description_code
)) as USAGE_TYPE
,decode(a.element_id, 0, '''', (
select h.description_text
from product_elements g
,descriptions h
where a.element_id = g.element_id
and g.description_code = h.description_code
)) as PRODUCT
,decode(a.jurisdiction, 0, '''', (
select j.description_text
from jurisdictions i
,descriptions j
where a.jurisdiction = i.jurisdiction
and j.description_code = i.description_code
)) as JURISDICTION
,decode(a.provider_class, 0, '''', (
select k.display_value
from provider_class_values k
where a.provider_class = k.provider_class
)) as PROVIDER
,decode(a.rate_period, '' 0 '', '''', (
select l.display_value
from rate_period_values l
where a.rate_period = l.rate_period
)) as RATE_PERIOD
,(a.FIXED_CHARGE_AMT / 100) + (a.ADD_FIXED_AMT / 10000000) as FLAGFALL
,(a.ADD_UNIT_RATE / 10000000) * 60 as RATE
,b.RATEBAND as RATEBAND
,b.NUM_UNITS as NUMSECS
,(b.UNIT_RATE / 10000000) * 60 as BAND_RATE
,a.ACTIVE_DT as ACTIVE_DT
,a.INACTIVE_DT as INACTIVE_DT
from rate_usage_overrides a
,rate_usage_bands_overrides b
where a.seqnum = b.seqnum(+);
I converted above code to nested loop and please find below converted nested loop and When I try to run this script below, it is prompting me an error: too many values. Can you tell me what exactly problem is
insert into PRICEVIEW_RATE_PLAN_PROC(
SSR_CODE,
CORRIDOR_PLAN_DESCRIPTION,
USAGE_TYPE,
PRODUCT,
JURISDICTION,
PROVIDER,
RATE_PERIOD,
FLAGFALL,
RATE,
RATEBAND,
NUMSECS,
BAND_RATE,
ACTIVE_DT,
INACTIVE_DT
) VALUES (
(select c.short_display AS SSR_CODE from rate_usage_overrides a,corridor_plan_id_values c where a.corridor_plan_id = c.corridor_plan_id),
(select d.display_value AS CORRIDOR_PLAN_DESCRIPTION from rate_usage_overrides a ,corridor_plan_id_values d where a.corridor_plan_id = d.corridor_plan_id),
(select f.description_text AS USAGE_TYPE from rate_usage_overrides a ,usage_types e, descriptions f where a.type_id_usg = e.type_id_usg and e.description_code = f.description_code ),
(select h.description_text AS PRODUCT from rate_usage_overrides a, product_elements g,descriptions h where a.element_id = g.element_id and g.description_code = h.description_code ),
(select j.description_text AS JURISDICTION from rate_usage_overrides a, jurisdictions i,descriptions j where a.jurisdiction = i.jurisdiction and j.description_code = i.description_code),
(select k.display_value AS PROVIDER from rate_usage_overrides a ,provider_class_values k where a.provider_class = k.provider_class),
(select l.display_value AS RATE_PERIOD from rate_usage_overrides a ,rate_period_values l where a.rate_period = l.rate_period),
(select (a.FIXED_CHARGE_AMT/100) + (a.ADD_FIXED_AMT/10000000) AS FLAGFALL from rate_usage_overrides a AS ACTIVE_DT),
(select (a.ADD_UNIT_RATE/10000000) * 60 AS RATE from rate_usage_overrides a),
(select b.RATEBAND AS RATEBAND from rate_usage_bands_overrides b),
(select b.NUM_UNITS AS NUMSECS from rate_usage_bands_overrides b),
(select (b.UNIT_RATE/10000000) * 60 AS BAND_RATE from rate_usage_bands_overrides b),
(select a.ACTIVE_DT,a.seqnum,b.seqnum AS ACTIVE_DT from rate_usage_overrides a, rate_usage_bands_overrides b where a.seqnum = b.seqnum(+)),
(select a.INACTIVE_DT,a.seqnum,b.seqnum AS INACTIVE_DT from rate_usage_overrides a, rate_usage_bands_overrides b where a.seqnum = b.seqnum(+))
Here is your mistake
(select a.ACTIVE_DT,a.seqnum,b.seqnum AS ACTIVE_DT from rate_usage_overrides a, rate_usage_bands_overrides b where a.seqnum = b.seqnum(+)),
(select a.INACTIVE_DT,a.seqnum,b.seqnum AS INACTIVE_DT from rate_usage_overrides a, rate_usage_bands_overrides b where a.seqnum = b.seqnum(+))
both the query will return 3 field but insert specify only one column that's why u are getting this error. and by the way this is not a bug
Run Individual queries with c.corridor_plan_id from 1st query on wards and check at least one query returns more than one value

Oracle Inner join on multiple tables returning null values

I am working on a sql inner join query which should return MAX elements from other tables. Tables B, C, D, E might be empty. In that case null should also be printed in output.
This is what I tried.
SELECT A.INDEX, A.CODE, MAX(B.DAY), MAX(C.TIMESTAMP), MAX(D.TIMESTAMP)
FROM A
INNER JOIN B
INNER JOIN C
INNER JOIN D
INNER JOIN E
ON A.INDEX = B.INDEX
ON A.INDEX = C.INDEX
ON A.INDEX = D.INDEX
ON A.INDEX = E.INDEX AND E.FUNCTION = 0;
Table definitions:
A
-------
INDEX NOT NULL NUMBER(10)
CODE NOT NULL VARCHAR2(16)
B
--------
INDEX NUMBER(10)
DAY NUMBER(10)
C
---------
INDEX NUMBER(10)
TIMESTAMP TIMESTAMP(6)
D
---------
INDEX NUMBER(10)
TIMESTAMP TIMESTAMP(6)
E
----------
INDEX NUMBER(10)
FUNCTION NUMBER(5)
In that case, consider doing a LEFT OUTER JOIN instead like
FROM A
LEFT JOIN B
So for your case
SELECT A.INDEX, A.CODE, MAX(B.DAY), MAX(C.TIMESTAMP), MAX(D.TIMESTAMP)
FROM A
LEFT JOIN B ON A.INDEX = B.INDEX
LEFT JOIN C ON A.INDEX = C.INDEX
LEFT JOIN D ON A.INDEX = D.INDEX
LEFT JOIN E ON A.INDEX = E.INDEX
AND E.FUNCTION = 0;

Duplicating rows in an oracle query

I am to create a query which will be used for printing labels in our project and find it difficult since the count of the number of labels is based on a string. I have made a query that looks like this:
SELECT
wipdatavalue
, containername
, l
, q as qtybox
, d
, qtyperbox AS q
, productname
, dt
, dsn
, CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, 1, instr(wipdatavalue, '-') - 1))
END AS una
, CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, instr(wipdatavalue, '-') + 1))
END AS dulo
, ROW_NUMBER() OVER (ORDER BY containername) AS n
, count(*) over() m
FROM trprinting_ls
WHERE containername = 'TRALTESTU0A'
GROUP BY wipdatavalue, containername, l, q, d, qtyperbox, productname, dt, dsn
ORDER BY wipdatavalue
The query above will result to below:
But actually, I have to display the first Item (Wipdatavalue 1-4) not only once but four times to look something like this:
I have tried another query that runs fine but when I try to load it in our project, it does not print the label. We found out that it is because of the WITH statement and we don't know why. The query is:
WITH DATA (WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo, m1, n)
AS (SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo,(dulo - una) + 1 AS m1,una n
FROM (SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYPERBOX AS QTYBOX, PRODUCTNAME, DT,
CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, 1, instr(wipdatavalue, '-') - 1))
END AS una,
CASE
WHEN instr(wipdatavalue, '-') = 0
THEN
to_number(wipdatavalue)
ELSE
to_number(substr(wipdatavalue, instr(wipdatavalue, '-') + 1))
END AS dulo
FROM trprinting_ls
WHERE containername = 'TRALTESTU0A'
)
UNION ALL
SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo, m1, n + 1
FROM DATA
WHERE n + 1 <= dulo)
SELECT WIPDATAVALUE, CONTAINERNAME, L, Q, D, QTYBOX, PRODUCTNAME, DT, una, dulo, n,
count(*) OVER () m
FROM DATA
ORDER BY n, wipdatavalue
Thanks guys for helping out.
Try this
select *
from your_data
start with instr(Wipdatavalue, '1') > 0
connect by level between regexp_substr(Wipdatavalue, '^\d+')
and regexp_substr(Wipdatavalue, '\d+$')
It's a simplified example
The regexp_substr can be replaced with substr and instr if you like (may also be faster)
Here is a sqlfiddle demo
Try this Query
select column_name, count(column_name)
from table
group by column_name
having count (column_name) > 1;

Selecting a sum from a correlated subquery - Oracle

I'm trying to change my code to have Oracle do all the heavy lifting. Originally, I had a function which did the following:
<!--- get common data --->
<cfquery name="getCommon">
SELECT x, NVL(SUM(y), 0) as y
FROM table_1
WHERE z between #this# and #that#
GROUP BY x
</cfquery>
<!--- place common values into a struct --->
<cfset oCommon = StructNew() >
<cfloop query="getCommon">
<cfset oCommon[x] = y >
</cfloop>
<!--- get records to loop through --->
<cfquery name="getSomething">
SELECT a, b, c/d as e from (
SELECT DISTINCT t2.a,
t2.b,
c,
sum(d)as d
FROM table_2 t2
LEFT JOIN table_3 t3
ON t2.a = t3.a
AND t2.b = t3.b
GROUP BY t2.a, t2.b, c
)
</cfquery>
<!--- loop through the results --->
<cfloop query="getSomething">
<!--- do an update to the target table if conditions are met --->
<!--- calculate my important new value --->
<cfset new_value = #getSomething.e# * #oCommon[b]# >
<!--- finally, insert my new values into the target table --->
<cfquery name="insertTarget">
INSERT INTO target_table(
a,
b,
c
)
VALUES (
#getSomething.a#,
#getSomething.b#,
#new_value#
)
</cfquery>
</cfloop>
I've already figured out how to use Oracle's MERGE to replace the update statement in the loop. My problem is the SQL to replace the insert statement. I'd like to be able to calculate the new value inside the SQL... once I get that, I think I can figure out the MERGE/insert part fairly easily.
So I want to do something like:
SELECT a, b, c/d*y as e from (
SELECT DISTINCT t2.a,
t2.b,
c,
sum(d)as d,
(
SELECT y FROM (
SELECT x, NVL(SUM(y), 0) as y
FROM table_1
WHERE z between #this# and #that#
AND x = t2.a
GROUP BY x
)
)
FROM table_2 t2
LEFT JOIN table_3 t3
ON t2.a = t3.a
AND t2.b = t3.b
GROUP BY t2.a, t2.b, c
)
which, perhaps obviously, doesn't work. Currently I get an ORA-00904: "t2"."a": Invalid Identifier, which isn't surprising.
So, I basically need to figure out how to get the sum of y from table_1, correlated by x = table_2.a, into the original getSomething query.
Edit: I tried this, but it's not quite right:
SELECT a, b, c/d*y as e from (
SELECT DISTINCT t2.a,
t2.b,
c,
sum(d)as d,
NVL(SUM(y), 0) as y
FROM table_2 t2
LEFT JOIN table_3 t3
ON t2.a = t3.a
AND t2.b = t3.b
LEFT JOIN table_1 t1
ON t1.x = t2.a
AND t1.z between #this# and #that#
GROUP BY t2.a, t2.b, c
)
You could write your query like this:
SELECT a, b, c / d * y AS e
FROM (SELECT DISTINCT t2.a,
t2.b,
c,
sum(d) AS d,
v.y
FROM table_2 t2
LEFT JOIN table_3 t3
ON t2.a = t3.a
AND t2.b = t3.b
LEFT JOIN (SELECT x, nvl(sum(y), 0) AS y
FROM table_1
WHERE z BETWEEN #this# AND #that#
GROUP BY x) v
ON t2.a = v.x
GROUP BY t2.a, t2.b, c, v.y)
The optimizer should be able to push the predicate t2.a = v.x into the subquery if it is convenient (for example if there is an index on table_1.x).
The sql sentence that worked for me is te following:
Select p.id,p.name, ( select sum(quantity) from details d where d.idproduct=p.id) sum from products p

Resources