Common table expression Alias Name issue - oracle

I am trying to insert column values of BREAK_TIME and DIFF_OUT into my base table ezlabor_final_ak using Common Table Expression(CTE) but it is giving error message
ORA-00904: "B"."IN_TIME": invalid identifier'
I am actually giving B as Alias name to my CTE but it is throwing error. Please help in rectifying the error. Please see the below code:
INSERT INTO ezlabor_final_ak(BREAK_TIME,DIFF_IN_OUT)
SELECT BREAK_TIME,DIFF_IN_OUT FROM (
WITH CTE_RN
AS
(
SELECT t.out_time,t.in_time,t.Employee,
ROW_NUMBER() OVER(ORDER BY In_Time) AS RN
FROM ezlabor_final_ak t
WHERE employee = 'JHW004605' AND TO_CHAR(in_time, 'dd/mm/yyyy') = '21/11/2013'
)
SELECT
a.Employee,TO_CHAR(a.in_time,'dd/mm/yyyy hh:mi:ss'),TO_CHAR(a.out_time,'dd/mm/yyyy hh:mi:ss'),a.RN as ARN,
TO_CHAR(p.out_time,'dd/mm/yyyy hh:mi:ss'),TO_CHAR(p.in_time,'dd/mm/yyyy hh:mi:ss'),p.RN AS PRN,
(a.in_time - p.out_time)*24*60 AS BREAK_TIME,
(a.OUT_TIME - a.IN_TIME)*24*60 AS DIFF_IN_OUT
FROM CTE_RN a
LEFT JOIN CTE_RN p
ON p.EMPLOYEE = a.EMPLOYEE AND
p.RN = a.RN - 1
WHERE a.employee = 'JHW004605' AND TO_CHAR(a.in_time, 'dd/mm/yyyy') = '21/11/2013'
) b
WHERE b.employee = 'JHW004605' AND TO_CHAR(b.in_time, 'dd/mm/yyyy') = '21/11/2013'

Related

ORA-00979 Not a Group function error for query with User defined function in select statement

I have this query where a user defined function is added in the select and group by statement.
The inner select query without the WITH clause runs fine and doesn't give any error. But after adding WITH clause it gives the following error -
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action: Error at Line: 3 Column: 29
I need the WITH clause to return only a subset of the entire result set based on input ranges.
Query is as follows:
WITH INFO AS (
SELECT
GET_EVAULATED_VALUE(T.C_IMP, T.IMP) AS IMPORTANCE,
count(*) AS NO_OF_PC_AFFECTED
FROM TABLE_NAME T
WHERE T.ACNT_REL_ID = 16
GROUP BY
(GET_EVAULATED_VALUE(T.C_IMP, T.IMP))
ORDER BY IMPORTANCE desc
)
SELECT * FROM
(
SELECT ROWNUM AS RN,
(SELECT COUNT(*) FROM INFO) COUNTS,
IMPORTANCE
FROM INFO
)
WHERE RN > 0 AND RN <= 10;
I am not sure how to use CTE with group by on user defined function. But I realized that I can rewrite the query to remove sub-query and CTE and make it simpler as following (and it works):
select * from (
select a.*, ROWNUM rnum from
(SELECT
count(*) over() as COUNTS,
GET_EVAULATED_VALUE(T.C_IMP, T.IMP) AS IMPORTANCE,
count(*) AS NO_OF_PC_AFFECTED
FROM TABLE_NAME T
WHERE T.ACNT_RELATION_ID = 16
GROUP BY
(GET_EVAULATED_VALUE(T.C_IMP, T.IMP))
ORDER BY importance desc) a
where ROWNUM <= 10 )
where rnum >= 0;
Same issue here, I created a table "TABLE_CTE" instead of using a CTE and it worked.
CREATE TABLE TABLE_CTE
AS
SELECT
USER_DEFINED_FUNCTION(date_1),
COUNT(*)
FROM
TABLE_NAME
GROUP BY
USER_DEFINED_FUNCTION(date_1)
;
SELECT * FROM TABLE_CTE

Why can't a query using 2 CTEs be linked to another table [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have something similar to the code below. I'm new to Oracle. It works fine until I try to join it to "anothertable" then states it can't see cte2.a. I can't find anything that explains why it can't see cte2.a
I need the data created by cte2 to further my query. Should i just do that inside of cte2 instead?
WITH cte 1 as (......),
cte2 as (....join tablename on tablename.x = cte1.x)
select *
from cte2
join anothertable on anothertable.a = cte2.a
Here is the actual query. It states "MAX_HEM"."PATIENT_ID": invalid identifier
WITH HGB AS(
SELECT DISTINCT
PH.PATIENT_ID,
PH.HEMATOLOGY_CD, --EX HGB
PH.PATIENT_HEMATOLOGY_ID,
PH.HEMATOLOGY_RESULT,
PH.TRANSACTION_DATE,
PH.TRANSACTION_TIME,
(TO_CHAR(PH.TRANSACTION_DATE) || ' ' || (TO_CHAR(TO_DATE(LPAD(PH.TRANSACTION_TIME,4,'0'),'HH24MI'),'HH:MI AM'))) AS HGB_DATETIME,
TO_NUMBER(TRIM(LEADING 0 FROM(TO_CHAR(ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME,'HH24MI')))) AS ISSUE_TIME,
ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME || ' ' || (TO_CHAR(ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME, 'HH:MI AM')) AS ISSUE_DTTM,
PRODUCT_INVENTORY.UNIT_NO,
CD_TRANSACTION.WTCODE
FROM
PRODUCT_INVENTORY_ACTIVITY PRODUCT_INVENTORY_ACTIVITY
JOIN CD_TRANSACTION CD_TRANSACTION ON PRODUCT_INVENTORY_ACTIVITY.TRANSACTION_CD = CD_TRANSACTION.TRANSACTION_CD
AND (CD_TRANSACTION.WTCODE='TA' OR CD_TRANSACTION.WTCODE='TX' OR CD_TRANSACTION.WTCODE='IE')
JOIN ORDER_PRODUCT_INVENTORY ORDER_PRODUCT_INVENTORY ON PRODUCT_INVENTORY_ACTIVITY.PRODINV_ID = ORDER_PRODUCT_INVENTORY.PRODINV_ID
JOIN ORDERS ORDERS ON ORDER_PRODUCT_INVENTORY.ORDER_ID = ORDERS.ORDER_ID
JOIN PATIENT_HEMATOLOGY PH ON PH.PATIENT_ID = ORDERS.PATIENT_ID
JOIN CD_ORDER_PRODUCT_INV_STAT CD_ORDER_PRODUCT_INV_STAT ON ORDER_PRODUCT_INVENTORY.ORDER_PRODUCT_INV_STAT_CD = CD_ORDER_PRODUCT_INV_STAT.ORDER_PRODUCT_INV_STAT_CD
JOIN PRODUCT_INVENTORY PRODUCT_INVENTORY ON ORDER_PRODUCT_INVENTORY.PRODINV_ID = PRODUCT_INVENTORY.PRODINV_ID
WHERE PH.HEMATOLOGY_CD = 'HGB'
AND PH.TRANSACTION_DATE <= TRUNC(ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME)
AND PH.TRANSACTION_TIME <= TO_NUMBER(TRIM(LEADING 0 FROM(TO_CHAR(ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME,'HH24MI'))))
AND CD_ORDER_PRODUCT_INV_STAT.WTCODE='TRANSFUSED'
AND (CD_TRANSACTION.WTCODE='TA' OR CD_TRANSACTION.WTCODE='TX' OR CD_TRANSACTION.WTCODE='IE')
AND ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME IS NOT NULL
AND (ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME>=TO_DATE ('01-09-2020 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
AND ORDER_PRODUCT_INVENTORY.ISSUE_DATETIME<TO_DATE ('06-09-2020 00:00:00', 'DD-MM-YYYY HH24:MI:SS'))
ORDER BY PH.PATIENT_ID, UNIT_NO,TO_DATE(PH.TRANSACTION_DATE) DESC, PH.TRANSACTION_TIME DESC
),
MAX_HEM AS
(
SELECT
HGB.PATIENT_ID "PatID",
MAX(HGB.PATIENT_HEMATOLOGY_ID) "HemID",
MAX(HGB.TRANSACTION_DATE) "TransDate",
MAX(HGB.TRANSACTION_TIME) "TransTime",
MAX(HGB.HEMATOLOGY_RESULT) "HGB_Results",
MAX(HGB.UNIT_NO) "UnitNo"
FROM PATIENT_HEMATOLOGY PH1
LEFT JOIN HGB ON PH1.PATIENT_ID = HGB.PATIENT_ID
GROUP BY HGB.PATIENT_ID
ORDER BY HGB.PATIENT_ID
)
select
HGB.*,
MAXHEM.*
FROM MAX_HEM
LEFT JOIN ORDERS ORDERS ON ORDERS.PATIENT_ID = MAX_HEM.PATIENT_ID
I tried the below and its working for me. Just check is it something like this you are expecting?
WITH cte AS
( select 'a' as a from dual
union
select 'g' as a from dual
), cte2 AS
(select 'a' as b from dual
union
select 'c' as b from dual
)
SELECT *
FROM cte c inner JOIN cte2 c2 ON c.a = c2.b
Your query works:
WITH cte1 (x) as (
SELECT dummy FROM DUAL
),
cte2 (x, a) as (
SELECT tablename.x,
tablename.a
FROM cte1
join tablename
on tablename.x = cte1.x
)
select *
from cte2
join anothertable
on anothertable.a = cte2.a;
Which, for the sample data:
CREATE TABLE tablename ( x, a ) AS
SELECT dummy, ROWNUM FROM DUAL;
CREATE TABLE anothertable ( a ) AS
SELECT ROWNUM FROM DUAL;
Outputs:
X | A | A
:- | -: | -:
X | 1 | 1
db<>fiddle here

Adding filters in subquery from CTE quadruples run time

I am working on an existing query for SSRS report that focuses on aggregated financial aid data split out into 10 aggregations. User wants to be able to select students included in that aggregated data based on new vs. returning and 'selected for verification.' For the new/returning status, I added a CTE to return the earliest admit date for a student. 2 of the 10 data fields are created by a subquery. I have been trying for 3 days to get the subquery to use the CTE fields for a filter, but they won't work. Either they're ignored or I get a 'not a group by expression' error. If I put the join to the CTE within the subquery, the query time jumps from 45 second to 400 seconds. This shouldn't be that complicated! What am I missing? I have added some of the code... 3 of the chunks work - paid_something doesn't.
with stuStatus as
(select
person_uid, min(year_admitted) admit_year
from academic_study
where aid_year between :AidYearStartParameter and :AidYearEndParameter
group by person_uid)
--- above code added to get student information not originally in qry
select
finaid_applicant_status.aid_year
, count(1) as fafsa_cnt --works
, sum( --works
case
when (
package_complete_date is not null
and admit.status is not null
)
then 1
else 0
end
) as admit_and_package
, (select count(*) --does't work
from (
select distinct award_by_aid_year.person_uid
from
award_by_aid_year
where
award_by_aid_year.aid_year = finaid_applicant_status.aid_year
and award_by_aid_year.total_paid_amount > 0 )dta
where
(
(:StudentStatusParameter = 'N' and stuStatus.admit_year = finaid_applicant_status.aid_year)
OR
(:StudentStatusParameter = 'R' and stuStatus.admit_year <> finaid_applicant_status.aid_year)
OR :StudentStatusParameter = '%'
)
)
as paid_something
, sum( --works
case
when exists (
select
1
from
award_by_person abp
where
abp.person_uid = fafsa.person_uid
and abp.aid_year = fafsa.aid_year
and abp.award_paid_amount > 0
) and fafsa.requirement is not null
then 1
else 0
end
) as paid_something_fafsa
from
finaid_applicant_status
join finaid_tracking_requirement fafsa
on finaid_applicant_status.person_uid = fafsa.person_uid
and finaid_applicant_status.aid_year = fafsa.aid_year
and fafsa.requirement = 'FAFSA'
left join finaid_tracking_requirement admit
on finaid_applicant_status.person_uid = admit.person_uid
and finaid_applicant_status.aid_year = admit.aid_year
and admit.requirement = 'ADMIT'
and admit.status in ('M', 'P')
left outer join stuStatus
on finaid_applicant_status.person_uid = stuStatus.person_uid
where
finaid_applicant_status.aid_year between :AidYearStartParameter and :AidYearEndParameter
and (
(:VerifiedParameter = '%') OR
(:VerifiedParameter <> '%' AND finaid_applicant_status.verification_required_ind = :VerifiedParameter)
)
and
(
(:StudentStatusParameter = 'N' and (stuStatus.admit_year IS NULL OR stuStatus.admit_year = finaid_applicant_status.aid_year ))
OR
(:StudentStatusParameter = 'R' and stuStatus.admit_year <> finaid_applicant_status.aid_year)
OR :StudentStatusParameter = '%'
)
group by
finaid_applicant_status.aid_year
order by
finaid_applicant_status.aid_year
Not sure if this helps, but you have something like this:
select aid_year, count(1) c1,
(select count(1)
from (select distinct person_uid
from award_by_aid_year a
where a.aid_year = fas.aid_year))
from finaid_applicant_status fas
group by aid_year;
This query throws ORA-00904 FAS.AID_YEAR invalid identifier. It is because fas.aid_year is nested too deep in subquery.
If you are able to modify your subquery from select count(1) from (select distinct sth from ... where year = fas.year) to select count(distinct sth) from ... where year = fas.year then it has the chance to work.
select aid_year, count(1) c1,
(select count(distinct person_uid)
from award_by_aid_year a
where a.aid_year = fas.aid_year) c2
from finaid_applicant_status fas
group by aid_year
Here is simplified demo showing non-working and working queries. Of course your query is much more complicated, but this is something what you could check.
Also maybe you can use dbfiddle or sqlfiddle to set up some test case? Or show us sample (anonimized) data and required output for them?

Update with a minimum value from a union in Oracle

UPDATE table1 t SET t.columnA =
(SELECT MIN(columnB) FROM
(SELECT columnB FROM table2
WHERE table2.fk = t.pk
UNION ALL
SELECT columnB FROM table3
WHERE table3.fk = t.pk))
gives me ORA-00904: "T"."PK": invalid identifier . Any ideas on how to achieve this?
This is a problem of scoping. Oracle does not recognize the outer query alias more than one level of nesting deep.
If we assume that values are in both tables, then you can use LEAST() with subqueries:
UPDATE table1 t
SET t.columnA = LEAST( (SELECT MIN(columnB)
FROM table2
WHERE table2.fk = t.pk
),
(SELECT MIN(columnB)
FROM table3
WHERE table2.fk = t.pk
)
);
If not, you can modify your query by moving the correlation clause out one level:
UPDATE table1 t
SET t.columnA = (SELECT MIN(columnB)
FROM ((SELECT table2.fk, columnB FROM table2
) UNION ALL
(SELECT table3.fk, columnB FROM table3
)
) tt
WHERE tt.fk = t.pk
);

ORA-00904 invalid identifier for nested select

I have been stuck on this error for 2 hours.
I have nested select to get the first value.
select tbl.table_name,
(select distinct(FirstItem)
from
(select first_value(column_name) over (order by timestamp asc rows unbounded predecing) as FirstItem
from log_table_b l
where tbl.assignment_no = l.rpt_no)
) as "USERNAME",
from prod_table tbl;
It returns this error:
ERROR at line 6:
ORA-00904: "TBL"."ASSIGNMENT_NO": invalid identifier
I have tried many things, none of them seems to be helping me.
You can't use the parent table in inner sub query. Here how you could achieve this :
with tmp_table as
(
select rpt_no, first_value(column_name) over (order by timestamp asc rows unbounded predecing) as FirstItem
from log_table_b l
) select distinct tbl.table_name, firstItem
from prod_table tbl
join tmpTable on tmp_table.rpt_no = tbl.assignment_no;
You might want to find a more descriptive name to tmp_table
The issue is that you can only pass a reference from an outer query down to the next subquery level.
Here are a couple of alternatives:
select tbl.table_name,
(select min(column_name) keep (dense_rank first order by tstamp asc)
from log_table_b l
where tbl.assignment_no = l.rpt_no
) as "USERNAME"
from prod_table tbl;
select tbl.table_name,
l.username
from prod_table tbl
inner join (select rpt_no,
min(column_name) keep (dense_rank first order by tstamp asc) username
from log_table_b l
group by rpt_no)
on (tbl.assignment_no = l.rpt_no);
N.B. untested

Resources