How can I bypass this issue? SQL Error ORA-00904 - sql

I'm into troubles with this code:
SELECT
s.codcli,
s.consfin consistenza_iniziale,
s.periodo,
ss.consfin consistenza_finale,
ss.periodo,
(SELECT sum(quanti) somma_bonifici_ingresso
FROM mov WHERE tipope IN ('VE1', 'VE5', 'VE9') AND (datope BETWEEN to_date('01-01-2016', 'DD-MM-YYYY') AND to_date('30-07-2017', 'DD-MM-YYYY')) AND mov.codcli = s.codcli
GROUP BY codcli, tipope) as somma_bonifici_ingresso,
(SELECT sum(quanti) somma_bonifici_ingresso
FROM mov WHERE tipope IN ('PR1', 'PR5', 'PR9') AND (datope BETWEEN to_date('01-01-2016', 'DD-MM-YYYY') AND to_date('30-07-2017', 'DD-MM-YYYY')) AND mov.codcli = s.codcli
GROUP BY codcli, tipope) as somma_bonifici_uscita,
(ss.consfin - (somma_bonifici_ingresso - somma_bonifici_uscita) - s.consfin)/s.consfin as variazione
FROM sre s
LEFT JOIN sre ss on s.codcli = ss.codcli
WHERE s.periodo=to_date('01-01-2016', 'DD-MM-YYYY')
AND ss.periodo=to_date('30-06-2017', 'DD-MM-YYYY')
AND s.consfin>0
ORDER BY s.codcli
I'm getting an 00904 error not a valid identifier. I need to insert a new column arranging the columns somma_bonifici_ingresso and somma_bonifici_uscita. I have to do some calculations but it seems like it isn't able to find those columns I guess for the aliases...

You cannot re-use a column alias in the same select, so use a subquery:
SELECT s.*,
(consistenza_iniziale - (somma_bonifici_ingresso - somma_bonifici_uscita) - consistenza_iniziale) / consistenza_iniziale as variazione
FROM (SELECT s.codcli, s.consfin as consistenza_iniziale, s.periodo,
ss.consfin as consistenza_finale, ss.periodo,
(SELECT sum(quanti)
FROM mov
WHERE tipope IN ('VE1', 'VE5', 'VE9') AND
(datope BETWEEN DATE '2016-01-01' AND DATE '2017-07-30') AND
mov.codcli = s.codcli
) as somma_bonifici_ingresso,
(SELECT sum(quanti)
FROM mov
WHERE tipope IN ('PR1', 'PR5', 'PR9') AND
(datope BETWEEN '2016-01-01' AND DATE '2017-07-30') AND
mov.codcli = s.codcli
) as somma_bonifici_uscita,
FROM sre s LEFT JOIN
sre ss
ON s.codcli = ss.codcli
WHERE s.periodo = DATE '2016-01-01' AND
ss.periodo = DATE '2017-07-30' AND
s.consfin > 0
) s
ORDER BY codcli;
Other notes:
Use date constants instead of literals. DATE for dates and TIMESTAMPS if there is a time.
Check your dates. There are differences between the dates in the subqueries and outer WHERE.
The GROUP BY is unnecessary -- and bad -- in the subqueries. You could end up with a "too many rows returned" error.

Related

how to use double group by and sum statements together in oracle

I am trying to use query below but it is giving an error
SELECT s.LOCAL_CODE,substr(p.ACCOUNT_CREDIT,-3),(p.SUMMA/100) as profit
FROM OPERATIONS s INNER JOIN LEADS p ON s.PAY_ID = p.PAY_ID
WHERE s.date_paid >= TO_DATE('03.12.2019', 'DD.MM.YYYY')
AND s.date_paid < TO_DATE('03.12.2019', 'DD.MM.YYYY') + INTERVAL '1' DAY
AND state = 'T'
AND s.filial_code = '006789'
AND SUBSTR(p.ACCOUNT_CREDIT, 1, 5) = '765294'
GROUP BY s.LOCAL_CODE,substr(p.ACCOUNT_CREDIT,-3);
If LEADS.SUMMA has expected value then you don't need Group By clause, else if you use Group By then all not grouped fields can be used only as arguments of aggregate functions:
SELECT s.LOCAL_CODE
, Substr(p.ACCOUNT_CREDIT, -3)
, Sum(p.SUMMA)/100 as profit
FROM OPERATIONS s
INNER JOIN LEADS p ON s.PAY_ID = p.PAY_ID
WHERE s.date_paid >= TO_DATE('03.12.2019', 'DD.MM.YYYY')
AND s.date_paid < TO_DATE('03.12.2019', 'DD.MM.YYYY') + INTERVAL '1' DAY
AND state = 'T'
AND s.filial_code = '006789'
AND SUBSTR(p.ACCOUNT_CREDIT, 1, 5) = '765294'
GROUP BY s.LOCAL_CODE
, substr(p.ACCOUNT_CREDIT, -3);

SQL subquery with average of 3 top values in Postgresql

I need a little help to solve a query to count patients (ID) who have the average of the 3 last diastolic tension (TAD) < 90.
I've tried several type of nested subqueries with different errors.
This is my last version I've done:
SELECT CENTRO, COUNT ( DISTINCT ID )
FROM
(
SELECT PAC.CENTRO, PAC.ID, T.TAD
FROM IDDPAC PAC,
(
SELECT AVG(TA.TAD) TAD
FROM
(
SELECT
TEXT_TO_NUMBER ( PAG.TEXTO ) TAD
FROM IDDPAG PAG, DATE D
WHERE TRIM ( PAG.DGP )='AH'
AND PAG.ID=T.ID
AND PAG.FECHA=D.OMI
AND D.TIME_DATE::DATE BETWEEN DATE '2012-01-01'
AND DATE '2012-12-31'
ORDER BY PAG.FECHA DESC LIMIT 3
) TA
) T
WHERE PAC.CENTRO='10040110' AND T.ID = PAC.ID
GROUP BY PAC.CENTRO , PAC.ID
)
A
WHERE T.TAD < 90
GROUP BY CENTRO
And I get the following error:
ERROR: falta una entrada para la tabla «t» en la cláusula FROM
LINE 31: AND PAG.ID=T.ID
^
********** Error **********
Translation:
ERROR: missing an entry for the table «t» in the clause FROM
LINE 31: AND PAG.ID=T.ID
^
********** Error **********
To get the average of the last three values, use row_number() to enumerate the values. Then choose the last three and take the average. This gives you the patient level information:
SELECT PAC.CENTRO, PAG.ID, AVG(TA.TAD) AS TAD
FROM (SELECT PAG.ID, TEXT_TO_NUMBER ( PAG.TEXTO ) as TAD,
ROW_NUMBER() OVER (PARTITION BY PAG.ID ORDER BY D.TIME_DATE DESC) as seqnum
FROM IDDPAG PAG JOIN
DATE D
ON PAG.FECHA = D.OMI JOIN
IDDPAC PAC
ON PAC.ID = PAG.ID
WHERE TRIM ( PAG.DGP )='AH' AND
D.TIME_DATE::DATE BETWEEN DATE '2012-01-01' AND DATE '2012-12-31'
) TA
WHERE SEQNUM <= 3
GROUP BY PAC.CENTRO, PAD.ID
HAVING AVG(TA.TAD) < 90;
The count by centro would just be:
SELECT CENTRO, COUNT(*)
FROM (SELECT PAC.CENTRO, PAG.ID, AVG(TA.TAD) AS TAD
FROM (SELECT PAG.ID, TEXT_TO_NUMBER ( PAG.TEXTO ) as TAD,
ROW_NUMBER() OVER (PARTITION BY PAG.ID ORDER BY D.TIME_DATE DESC) as seqnum
FROM IDDPAG PAG JOIN
DATE D
ON PAG.FECHA = D.OMI JOIN
IDDPAC PAC
ON PAC.ID = PAG.ID
WHERE TRIM ( PAG.DGP )='AH' AND
D.TIME_DATE::DATE BETWEEN DATE '2012-01-01' AND DATE '2012-12-31'
) TA
WHERE SEQNUM <= 3
GROUP BY PAC.CENTRO, PAD.ID
HAVING AVG(TA.TAD) < 90
) TA
GROUP BY CENTRO;
The problem is, exactly as the error indicates, that 'T' is not defined in the place it is requested. Your error is in the innermost subquery:
SELECT
TEXT_TO_NUMBER ( PAG.TEXTO ) TAD
FROM IDDPAG PAG, DATE D
WHERE TRIM ( PAG.DGP )='AH'
AND PAG.ID=T.ID
AND PAG.FECHA=D.OMI
AND D.TIME_DATE::DATE BETWEEN DATE '2012-01-01'
AND DATE '2012-12-31'
ORDER BY PAG.FECHA DESC LIMIT 3
But there is no T defined here to be used in the PAG.ID=T.ID portion of your WHERE clause. Did you mean to join on a table called T? Or did you mean to use D.ID instead?

SQL Oracle Query - Left Outer Join on null Field

I have this query
SELECT *
FROM (SELECT mi.visit_id, mi.event_id, mi.patient_id, mi.mrn, mi.reg_date,
mi.d_date, mi.bml_count, mi.TYPE, mblp.baby_patient_id,
mblp.baby_birthdate
FROM ajmid.km0076_motherinfo_test mi LEFT JOIN alfayezb2.mbl_patients mblp
ON mblp.mother_patient_id = mi.patient_id
--works here
AND ( TO_CHAR (mblp.baby_birthdate, 'mm/dd/YYYY') =
TO_CHAR (mi.reg_date, 'mm/dd/YYYY')
OR TO_CHAR (mblp.baby_birthdate, 'mm/dd/YYYY') =
TO_CHAR (mi.reg_date - 1, 'mm/dd/YYYY')
OR TO_CHAR (mblp.baby_birthdate, 'mm/dd/YYYY') =
TO_CHAR (mi.reg_date + 1, 'mm/dd/YYYY')
)
) bml
LEFT OUTER JOIN --doesn't work here
(SELECT ROW_NUMBER () OVER (PARTITION BY vis.patient_id ORDER BY vis.admission_date_time)
num,
vis.admission_date_time, vis.visit_id, vis.patient_id,
vis.facility_id
FROM visit vis) v ON bml.baby_patient_id = v.patient_id
WHERE v.num = 1
ORDER BY bml.reg_date
bml by itself returns 118 rows while the whole query returns 117, the reason is bml returns 1 row with baby_patient_id as null, so I used left outer join to show it, but it's still not showing !!
what can I do to show all rows of bml ?
I'm using Toad 9.6
Thank you
check the query:
SELECT ROW_NUMBER () OVER (PARTITION BY vis.patient_id ORDER BY vis.admission_date_time)
num,
vis.admission_date_time, vis.visit_id, vis.patient_id,
vis.facility_id
FROM visit vis
does it return 118 not null patient_id's?
if it returns 117, that might be the reason.(LEFT OUTER JOIN doesnot pick the records which are null on both tables)
Also, are you sure the null value of baby_patient_id in bml table is actually a NULL value and not a empty charater?(' ').
The probable cause is your filter / criteria (where clause) is eliminating a row with a null value for v.num. The WHERE filters the results after the join.
WHERE v.num = 1 -- Are all v.num equal to 1 ?
The mere action of using a criteria against a field, by definition of what NULL means, eliminates that row from consideration because NULL cannot be evaluated. You can say "WHERE id != 1" and expect to get rows where id is null because null != 1 right? Wrong. id != NULL is not defined logically. It is why we say "IS or IS NOT NULL" when dealing with NULL.
it's working finally !
I added
OR bml.baby_patient_id IS NULL
to the where clause, so the final script is
SELECT *
FROM (SELECT mi.visit_id, mi.event_id, mi.patient_id, mi.mrn, mi.reg_date,
mi.d_date, mi.bml_count, mi.TYPE, mblp.baby_patient_id,
mblp.baby_birthdate
FROM ajmid.km0076_motherinfo_test mi LEFT JOIN alfayezb2.mbl_patients mblp
ON mblp.mother_patient_id = mi.patient_id
AND ( TO_CHAR (mblp.baby_birthdate, 'mm/dd/YYYY') =
TO_CHAR (mi.reg_date, 'mm/dd/YYYY')
OR TO_CHAR (mblp.baby_birthdate, 'mm/dd/YYYY') =
TO_CHAR (mi.reg_date - 1, 'mm/dd/YYYY')
OR TO_CHAR (mblp.baby_birthdate, 'mm/dd/YYYY') =
TO_CHAR (mi.reg_date + 1, 'mm/dd/YYYY')
)
) bml
LEFT OUTER JOIN
(SELECT ROW_NUMBER () OVER (PARTITION BY vis.patient_id ORDER BY vis.admission_date_time)
num,
vis.admission_date_time, vis.visit_id, vis.patient_id,
vis.facility_id
FROM visit vis) v ON bml.baby_patient_id = v.patient_id
WHERE v.num = 1
OR bml.baby_patient_id IS NULL
ORDER BY bml.reg_date
I don't know how this was helpful, I wish someone would explain for me !
Thanks all

Convert a nested subquery into normal query

I have problem with following query where in which the nested query should be
converted to normal query:
select
count(*) as count,
TO_CHAR(RH.updated_datetime,'DD-MM-YYYY HH:MI:SS') as date,
SUM(
extract (
epoch from (
RH.updated_datetime - PRI.procedure_performed_datetime
)
)/60
)::integer/count(*) as diff
from
procedure_runtime_information PRI,
study S,
report R,
report_history RH
where
RH.report_fk = R.pk AND
R.study_fk = S.pk AND
S.procedure_runtime_fk = PRI.pk AND
RH.old_status_fk = 21 AND
RH.revision = (select max(revision) from report_history where RH.report_fk = RH.report_fk) AND
RH.updated_datetime > TO_DATE('22-01-2013 00:00:00', 'DD-MM-YYYY HH24:MI:SS') AND RH.updated_datetime < TO_DATE('22-01-2014 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
group by date order by date asc;
Assuming this
(select max(revision) from report_history where RH.report_fk = RH.report_fk)
should really be:
(select max(revision) from report_history x where x.report_fk = RH.report_fk)
You could transform the nested (correlated) subquery into a plain subquery like this (one way of many):
SELECT count(*) AS ct
,to_char(rh.updated_datetime,'DD-MM-YYYY HH:MI:SS') AS date -- HH24?
,sum(extract(epoch FROM (RH.updated_datetime
- PRI.procedure_performed_datetime))
/ 60)::int / count(*) AS diff
FROM procedure_runtime_information PRI
JOIN study S ON S.procedure_runtime_fk = PRI.pk
JOIN report R ON R.study_fk = S.pk
JOIN report_history RH ON RH.report_fk = R.pk
JOIN (
SELECT report_fk, max(revision) AS revision
FROM report_history RH1
GROUP BY 1
) RH1 ON RH1.report_fk = RH.report_fk
AND RH1.revision = RH.revision
WHERE RH.old_status_fk = 21
AND RH.updated_datetime > to_date('22-01-2013', 'DD-MM-YYYY') -- >= ?
AND RH.updated_datetime < to_date('22-01-2014', 'DD-MM-YYYY') -- to_timestamp?
GROUP BY date -- where does date come from?
ORDER BY date;

Oracle ORA-00979 - "not a GROUP BY expression"

Can anybody please help me with this particular query? I'm having ORA-00979 when trying to run this:
select t0.title, count (1) as count0, (select count (1)
from contract c1, se se1
where c1.c_id = se1.c_id
and se1.svc_id = 3
and se1.deleted = 0
and c1.deleted = 0
and c1.c_date between to_date ('07.10.2000', 'dd.mm.yyyy')
and to_date ('22.11.2010', 'dd.mm.yyyy')
and c1.company = 0
and c1.tdata.tariff = c0.tdata.tariff
) as count1
from contract c0, se se0, tariff t0
where c0.c_id = se0.c_id
and se0.svc_id = 3
and se0.deleted = 0
and c0.deleted = 0
and c0.c_date between to_date ('21.11.2000', 'dd.mm.yyyy')
and to_date ('06.01.2011', 'dd.mm.yyyy')
and c0.company = 0
and t0.tariff_id = c0.tdata.tariff
group by t0.title
The problem is your subquery with the select count(1) part. Just because it's got a count in it doesn't actually make it an aggregate. It's still a subquery that will be applied to every row and as you can see it uses the value c0.tdata.tariff which is not part of the group.
Looks like that scalar subquery is causing the problem -- it is neither a group function, nor is it in the GROUP BY list.
Probably you could workaround it with something like:
select t0.title, count (1) as count0, SUM(select count (1) ...) AS count1
...
Considering this seems to be two instances of the same query just over different dates (I might be wrong here...it's been a long day), you could probably just simplify it and rewrite like this:
select
t0.title,
count (case when c0.c_date between to_date ('21.11.2000', 'dd.mm.yyyy')
and to_date ('06.01.2011', 'dd.mm.yyyy') then 1 end) as count0,
count (case when c0.c_date between to_date ('07.10.2000', 'dd.mm.yyyy')
and to_date ('22.11.2011', 'dd.mm.yyyy') then 1 end) as count1
from
contract c0,
se se0,
tariff t0
where
c0.c_id = se0.c_id
and se0.svc_id = 3
and se0.deleted = 0
and c0.deleted = 0
and (c0.c_date between to_date ('21.11.2000', 'dd.mm.yyyy')
and to_date ('06.01.2011', 'dd.mm.yyyy')
or c0.c_date between to_date ('07.10.2000', 'dd.mm.yyyy')
and to_date ('22.11.2010', 'dd.mm.yyyy'))
and c0.company = 0
and t0.tariff_id = c0.tdata.tariff
group by t0.title
Your group by needs to include all of the non-aggregate columns from your select list. In this case, the group by is missing the count1 returned by your subquery.