Oracle sub error on query - sql

Following code I added to the SQL Server query and now have to do the same in Oracle. I need to do grouping in the view rather than in the C#. I get this error message:
ORA-01747 Invalid user.table.column or column specification.
How must I code this to work in Oracle?
SELECT CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS, COUNT(*) AS [COUNT]
FROM CTE
GROUP BY CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS;
at the beginning of query I have this full code here:
CREATE OR REPLACE VIEW DBD_V_CDL_CHANGES AS
WITH CTE AS
(
SELECT TR.FACILITY_KEY
, MV.VALUE_CODE
, CAST(COUNT(*) AS NUMERIC(9, 0)) COUNT
FROM OPTC.THS_T_TRANSACTIONS1 TR
JOIN OPTC.THS_M_MENU2 M
ON M.MENU_ID = TR.MENU_ID
JOIN OPTC.THS_M_VALUES MV
ON MV.MENU_ID = TR.MENU_ID_VALUE
JOIN OPTC.THS_M_VALUES MV2
ON MV2.MENU_ID = TR.PREVIOUS_MENU_ID_VALUE
JOIN OGEN.GEN_M_PATIENT_MAST PM
ON PM.PAT_NUMBER = TR.PAT_NUMBER
WHERE TR.TR_DATETIME BETWEEN TRUNC(SYSDATE)
AND TRUNC(SYSDATE) + 86399 / 86400
AND TR.EDIT_NO < 0
AND MV.VALUE_TYPE IS NULL
AND MV2.VALUE_TYPE IS NULL
AND MV.VALUE_CODE >= 0
AND MV2.VALUE_CODE >= 0
AND M.SUB_SYS_EXT = 'G1'
AND ABS(MV.VALUE_CODE - MV2.VALUE_CODE) > 1
AND (PM.DISCHARGE_DATE IS NULL OR PM.DISCHARGE_DATE < SYSDATE)
GROUP BY TR.FACILITY_KEY, MV.VALUE_CODE)
SELECT CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS, COUNT(*) AS [COUNT] FROM CTE
GROUP BY CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS;

I see a few things wrong with your code.
First, you are selecting the following three columns FACILITY_KEY, VALUE_CODE and the count in the CTE:
SELECT TR.FACILITY_KEY ,
MV.VALUE_CODE ,
COUNT(*) as Count -- note there is no need to CAST(COUNT(*) AS NUMERIC(9, 0)) this
FROM OPTC.THS_T_TRANSACTIONS1 TR
But then when you select from the CTE you are selecting columns that you are not returning in the CTE:
with cte as
(
-- your query here does not return DATE or PATIENT_STATUS
)
SELECT CTE.FACILITY_KEY,
CTE.DATE,
CTE.PATIENT_STATUS,
COUNT(*) AS COUNT
FROM CTE
GROUP BY CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS;
Where do PATIENT_STATUS and Date come from since you are not including them in your CTE? So these do not exist when you are trying to select them.
I replicated your error by including columns in the list that were not select in the CTE query.
The second issue is the CTE.DATE column. DATE is a reserved word, place that is double quotes CTE."DATE"

...AS [COUNT], ...AS NUMERIC(9, 0)) is not Oracle syntax and will never work. Simply remove [ ] and use NUMBER instead of NUMERIC. There is no need to CAST Count(). The Count() function will always return number, e.g. 0-zero or some number.
This is valid syntax in Oracle:
SELECT deptno, count(*) total_count_by_dept -- no need to cast or AS --
FROM scott.emp
GROUP BY deptno
/
Try not to use reserved words as COUNT for aliases:
SELECT CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS, COUNT(*) AS total_cnt -- 'AS' is for clarity only, not required
FROM CTE
GROUP BY CTE.FACILITY_KEY, CTE.DATE, CTE.PATIENT_STATUS
/

Related

How to combine 2 SQL statements into one table

I have 2 SQL statements to look up successful transactions and failed transactions.
SELECT COUNT (code_reseller) as trx_success, kode_reseller
FROM transaksi
where status = '20' AND CAST (date_entri AS DATE) = CAST (GETDATE() AS DATE)
group by code_reseller
ORDER BY trx_success DESC
AND
SELECT COUNT (code_reseller) as trx_fail, kode_reseller
FROM transaksi
where status > '20' AND CAST (date_entri AS DATE) = CAST (GETDATE() AS DATE)
group by code_reseller
ORDER BY trx_fail DESC
How to combine into one table with 3 columns result with code_reseller, trx_success and trx_fail?
Use conditional aggregation and combine the queries:
SELECT
kode_reseller,
COUNT(CASE WHEN status = '20' THEN 1 END) AS trx_success,
COUNT(CASE WHEN status > '20' THEN 1 END) AS trx_fail
FROM transaksi
WHERE
CAST(date_entri AS DATE) = CAST(GETDATE() AS DATE)
GROUP BY
kode_reseller;
The strategy here is to move the filtering on the status column which previously appeared in the two WHERE clauses into the conditional counts in the SELECT clause. The restriction on date_entri can stay there, since both queries have it.
As suggested by #Dale k, you can do it like this.
You cannot add order by inside, so create an alias table and give order by condition.
SELECT *
FROM
(
SELECT COUNT (code_reseller) as trx_success, kode_reseller
FROM transaksi
WHERE status = '20' AND CAST (date_entri AS DATE) = CAST (GETDATE() AS DATE)
GROUP BY code_reseller
UNION ALL
SELECT COUNT (code_reseller) as trx_fail, kode_reseller
FROM transaksi
WHERE status > '20' AND CAST (date_entri AS DATE) = CAST (GETDATE() AS DATE)
GROUP BY code_reseller
) a
ORDER BY a.trx_success DESC --here we get first select query table' column name and datatype and no of column will be same required in union/union all

How to select data without using group?

My base data based on dealer code only but in one condition we need to select other field as well to matching the condition in other temp table how can i retrieve data only based on dealercode ith matching the condition on chassis no.
Below is the sample data:
This is how we have selected the data for the requirement:
---------------lastyrRenewalpolicy------------------
IF OBJECT_ID('TEMPDB..#LASTYRETEN') IS NOT NULL DROP TABLE #LASTYRETEN
select DEALERMASTERCODE , count(*) RENEWALEXPRPOLICY,SUM(NETOD_YEAR_PREM_PART_A) AS 'ACHIEVED-ODPREMIUM_RENEWAL' into #LASTYRETEN
from [dbo].[T_RE_POLICY_TRANSACTION]
where cast (InsPolicyCreatedDate as date) between #FirstDayC and #LastDayC
AND PolicyStatus= 'Renewal' AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by DEALERMASTERCODE
-----------------lastrollower------------------------
IF OBJECT_ID('TEMPDB..#LASTYROLWR') IS NOT NULL DROP TABLE #LASTYROLWR
select DEALERMASTERCODE , count(*) ROLLOWEEXPRPOLICY ,SUM(NETOD_YEAR_PREM_PART_A) AS 'ACHIEVED-ODPREMIUM_ROLLOVER'
into #LASTYROLWR from [dbo].[T_RE_POLICY_TRANSACTION] where cast (InsPolicyCreatedDate as date) between #FirstDayC and #LastDayC
AND PolicyStatus= 'ROLLOVER' AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by DEALERMASTERCODE
And continue with above flow Below is the other select statement which creating issue at the end due to grouping
:
-------------OTHERYRBASE(EXPIRYRENEWAL)--------------
IF OBJECT_ID('TEMPDB..#OTHERYRBASEEXPIRY') IS NOT NULL DROP TABLE #OTHERYRBASEEXPIRY
select DEALERMASTERCODE ,ChassisNo , count(*) RENEWALPOLICYEXPIRY
into #OTHERYRBASEEXPIRY
from [dbo].[T_RE_POLICY_TRANSACTION] where cast (PolicyExpiryDate as date) between '2020-08-01' and '2020-08-31'
and BASIC_PREM_TOTAL <> 0 AND PolicyStatus in ('Renewal','rollover') and BusinessType='jcb'
AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by DEALERMASTERCODE,ChassisNo
-------------OTHERYRBASE(EXPIRYRENEWAL)--------------
IF OBJECT_ID('TEMPDB..#OTHERYRCON') IS NOT NULL DROP TABLE #OTHERYRCON
select OTE.DEALERMASTERCODE ,OTE.ChassisNo , count(*) OTHERYRCON into #OTHERYRCON
from [dbo].[T_RE_POLICY_TRANSACTION] OTE INNER JOIN #OTHERYRBASEEXPIRY EXP
ON OTE.ChassisNo=EXP.ChassisNo
where cast(CREATED_DATE as date) between '2020-06-01' and '2020-12-31' and BusinessType='jcb'
and OTE.BASIC_PREM_TOTAL <> 0 AND OTE.PolicyStatus = 'Renewal'
AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 ) group by OTE.DEALERMASTERCODE,OTE.ChassisNo
Thanks a lot in advance for helping and giving a solution very quickly ///
After taking a look at this code it seems possible there was an omitted JOIN condition in the last SELECT statement. In the code provided the JOIN condition is only on ChassisNo. The GROUP BY in the prior queries which populates the temporary table also included the DEALERMASTERCODE column. I'm thinking DEALERMASTERCODE should be added to the JOIN condition. Something like this
select OTE.DEALERMASTERCODE ,OTE.ChassisNo , count(*) OTHERYRCON
into #OTHERYRCON
from [dbo].[T_RE_POLICY_TRANSACTION] OTE
INNER JOIN #OTHERYRBASEEXPIRY EXP ON OTE.DEALERMASTERCODE=EXP.DEALERMASTERCODE
and OTE.ChassisNo=EXP.ChassisNo
where cast(CREATED_DATE as date) between '2020-06-01' and '2020-12-31'
and BusinessType='jcb'
and OTE.BASIC_PREM_TOTAL <> 0
AND OTE.PolicyStatus = 'Renewal'
AND (ltrim(rtrim(ISCANCELLEDSTATUS)) = 0 )
group by OTE.DEALERMASTERCODE,OTE.ChassisNo;

Invalid identifier in pivot table

Here is my query:
SELECT NVL(REVENUE,0), OUTNO, MONTH_NAME FROM
(
SELECT ROUND((RETURNDATE-STARTDATE)*DAILYRATE) AS REVENUE,
OUTNO,
EXTRACT(MONTH FROM RETURNDATE)AS MONTH_NAME
FROM RAGREEMENT LEFT JOIN VEHICLE ON
RAGREEMENT.LICENSENO=VEHICLE.LICENSENO
AND EXTRACT(YEAR FROM RETURNDATE)=EXTRACT(YEAR FROM SYSDATE)-1
)
PIVOT (
SUM(REVENUE)
FOR OUTNO IN (1,2,3,4,5,6,-1 AS TOTAL)
)
ORDER BY MONTH_NAME;
and here is the error
SELECT NVL(REVENUE,0), OUTNO, MONTH_NAME FROM
*
ERROR at line 1:
ORA-00904: "OUTNO": invalid identifier
I fail to understand why this happens when SELECT * works perfectly
What comes out from a pivot is a whole new set of columns names, and for each one of those new columns, you will need an NVL() or COALESCE(). This is because a completely new "matrix" is formed and many positions in this can be null. You cannot overcome this by using NVL() in the inner subquery.
Assuming you want months as columns your query might look more like this:
SELECT
OUTNO
, NVL('M1', 0)
, NVL('M2', 0)
, NVL('M3', 0)
, NVL('M4', 0)
, NVL('M5', 0)
, NVL('M6', 0)
, NVL('M7', 0)
, NVL('M8', 0)
, NVL('M9', 0)
, NVL('M10', 0)
, NVL('M11', 0)
, NVL('M12', 0)
FROM (
SELECT
ROUND((RETURNDATE - STARTDATE) * DAILYRATE) AS REVENUE
, OUTNO
, 'M' || EXTRACT(MONTH FROM RETURNDATE) AS MONTH_NAME
FROM RAGREEMENT
LEFT JOIN VEHICLE ON RAGREEMENT.LICENSENO = VEHICLE.LICENSENO
AND EXTRACT(YEAR FROM RETURNDATE) = EXTRACT(YEAR FROM SYSDATE) - 1
)
PIVOT(
SUM(REVENUE)
FOR MONTH_NAME IN ('M1','M2','M3','M4','M5','M6','M7','M8','M9','M10','M11','M12')
)
ORDER BY OUTNO;
This line produces the new columns:
FOR MONTH_NAME IN ('M1','M2','M3','M4','M5','M6','M7','M8','M9','M10','M11','M12')
and it is each one of these you will need to "fix" for nulls in the select clause.
To put OUTNO values into columns requires a similar pattern but you need to know what the distinct set of values will be from that originating column. This MIGHT be 1,2,3,4,5,6,-1 but I wasn't certain.
nb: I prefixed 'M' in columns headings as many systems object to numbers as heading names.

I created a column in the select; how do i use it in the where?

I created a column in the select statement (DaysSinceCheck).
How do I use it in my WHERE clause?
SELECT DISTINCT
Name,
(DATEDIFF(D, max(lastDaTe), GETDATE())) AS DaysSinceCheck
FROM
event_table
WHERE
cust = 'usa'
AND ((DATEDIFF(D, max(lastDaTe), GETDATE()))) <= 2
GROUP BY
Name
Receiving the error:
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
You test the value of an aggregate function using a HAVING clause.
...
WHERE cust = 'usa'
GROUP BY Name
HAVING ((DATEDIFF(D, max(lastDaTe), GETDATE()))) <= 2
The HAVING solution works fine... an alternate way is using a CTE to break things into two parts like this:
WITH NameAndDays AS (
SELECT DISTINCT Name,
(DATEDIFF(D, max(lastDaTe), GETDATE())) AS DaysSinceCHECK
FROM event_table
WHERE cust = 'usa'
GROUP BY Name
) SELECT *
FROM NameAndDays
WHERE DaysSinceCHECK <= 2

Filling in missing dates DB2 SQL

My initial query looks like this:
select process_date, count(*) batchCount
from T1.log_comments
order by process_date asc;
I need to be able to do some quick analysis for weekends that are missing, but wanted to know if there was a quick way to fill in the missing dates not present in process_date.
I've seen the solution here but am curious if there's any magic hidden in db2 that could do this with only a minor modification to my original query.
Note: Not tested, framed it based on my exposure to SQL Server/Oracle. I guess this gives you the idea though:
*now amended and tested on DB2*
WITH MaxDateQry(MaxDate) AS
(
SELECT MAX(process_date) FROM T1.log_comments
),
MinDateQry(MinDate) AS
(
SELECT MIN(process_date) FROM T1.log_comments
),
DatesData(ProcessDate) AS
(
SELECT MinDate from MinDateQry
UNION ALL
SELECT (ProcessDate + 1 DAY) FROM DatesData WHERE ProcessDate < (SELECT MaxDate FROM MaxDateQry)
)
SELECT a.ProcessDate, b.batchCount
FROM DatesData a LEFT JOIN
(
SELECT process_date, COUNT(*) batchCount
FROM T1.log_comments
) b
ON a.ProcessDate = b.process_date
ORDER BY a.ProcessDate ASC;