Execute Select query in end of function - sql

I have CTE as bellow,
WITH extract_dow AS (
SELECT EXTRACT(DOW FROM TIMESTAMP '1994-03-15'::DATE) AS dow
)
,name_day AS(
SELECT
CASE WHEN dow = 0 THEN (SELECT 'Minggu'::TEXT AS day)
ELSE
CASE WHEN dow = 1 THEN (SELECT 'Senin'::TEXT AS day)
ELSE
CASE WHEN dow = 2 THEN (SELECT 'Selasa'::TEXT AS day)
ELSE
CASE WHEN dow = 3 THEN (SELECT 'Rabu'::TEXT AS day)
ELSE
CASE WHEN dow = 4 THEN (SELECT 'Kamis'::TEXT AS day)
ELSE
CASE WHEN dow = 5 THEN (SELECT 'Jumat'::TEXT AS day)
ELSE
CASE WHEN dow = 6 THEN (SELECT 'Sabtu'::TEXT AS day)
ELSE (SELECT 'Inputan Salah'::TEXT AS day)
END
END
END
END
END
END
END
FROM extract_dow
)
, extract_age AS (
SELECT ((CURRENT_DATE - '1994-03-15'::DATE)/365) AS age
)
SELECT 'Anda Lahir :' || a.day || ',' || b.age || ' Tahun' AS "Keterangan" FROM name_day a, extract_age b
Its to generate day in text of date '1994-03-15' and age calculate from current, when its execute we have in output:
"Anda Lahir :Selasa,24 Tahun"
When I Try to convert it to function as bellow:
> -- Function: function_birthday(date)
>
> -- DROP FUNCTION function_birthday(date);
>
> CREATE OR REPLACE FUNCTION function_birthday(inputan date)
> RETURNS text AS
> $BODY$
> DECLARE
> perintah text;
> BEGIN
>
> perintah := $sql$
>
> WITH extract_dow AS ( SELECT EXTRACT(DOW FROM TIMESTAMP '$sql$ || inputan || $sql$'::DATE) AS dow )
> ,name_day AS( SELECT CASE WHEN dow = 0 THEN (SELECT 'Minggu'::TEXT AS day)
> ELSE CASE WHEN dow = 1 THEN (SELECT 'Senin'::TEXT AS day)
> ELSE
> CASE WHEN dow = 2 THEN (SELECT 'Selasa'::TEXT AS day)
> ELSE
> CASE WHEN dow = 3 THEN (SELECT 'Rabu'::TEXT AS day)
> ELSE
> CASE WHEN dow = 4 THEN (SELECT 'Kamis'::TEXT AS day)
> ELSE
> CASE WHEN dow = 5 THEN (SELECT 'Jumat'::TEXT AS day)
> ELSE
> CASE WHEN dow = 6 THEN (SELECT 'Sabtu'::TEXT AS day)
> ELSE (SELECT 'Inputan Salah'::TEXT AS day)
> END
> END
> END
> END
> END
> END
> END FROM extract_dow )
>
>
> , extract_age AS ( SELECT ((CURRENT_DATE - '$sql$ || inputan || $sql$'::DATE)/365) AS age)
> SELECT 'Anda Lahir :' || a.day || ',' || b.age || ' Tahun' AS "Keterangan" FROM name_day a, extract_age b
>
> RETURN *;
> $sql$;
> EXECUTE perintah;
> END;
> $BODY$
> LANGUAGE plpgsql VOLATILE COST 100;
> ALTER FUNCTION function_birthday(date)
> OWNER TO postgres;
But when im execute it with
SELECT public.function_birthday('1994-03-15');
I have error
ERROR: syntax error at or near "RETURN"
LINE 36: RETURN *;
CONTEXT: PL/pgSQL function function_birthday(date) line 43 at EXECUTE statement
********** Error **********
ERROR: syntax error at or near "RETURN"
SQL state: 42601
Context: PL/pgSQL function function_birthday(date) line 43 at EXECUTE statement
My question is, where is the error from my function, or i am write in wrong structure of the function, i had searching and looking for to solve it (How to convert my CTE to function)?
Thanks for Help, ^_^

You could try:
> -- Function: function_birthday(date)
>
> -- DROP FUNCTION function_birthday(date);
>
> CREATE OR REPLACE FUNCTION function_birthday(inputan date)
> RETURNS text AS
> $BODY$
> DECLARE
> perintah text;
> result text;
> BEGIN
>
> perintah := $sql$
>
> WITH extract_dow AS ( SELECT EXTRACT(DOW FROM TIMESTAMP '$sql$ || inputan || $sql$'::DATE) AS dow )
> ,name_day AS( SELECT CASE WHEN dow = 0 THEN (SELECT 'Minggu'::TEXT AS day)
> ELSE CASE WHEN dow = 1 THEN (SELECT 'Senin'::TEXT AS day)
> ELSE
> CASE WHEN dow = 2 THEN (SELECT 'Selasa'::TEXT AS day)
> ELSE
> CASE WHEN dow = 3 THEN (SELECT 'Rabu'::TEXT AS day)
> ELSE
> CASE WHEN dow = 4 THEN (SELECT 'Kamis'::TEXT AS day)
> ELSE
> CASE WHEN dow = 5 THEN (SELECT 'Jumat'::TEXT AS day)
> ELSE
> CASE WHEN dow = 6 THEN (SELECT 'Sabtu'::TEXT AS day)
> ELSE (SELECT 'Inputan Salah'::TEXT AS day)
> END
> END
> END
> END
> END
> END
> END FROM extract_dow )
>
>
> , extract_age AS ( SELECT ((CURRENT_DATE - '$sql$ || inputan || $sql$'::DATE)/365) AS age)
> SELECT 'Anda Lahir :' || a.day || ',' || b.age || ' Tahun' AS "Keterangan" FROM name_day a, extract_age b
>
> $sql$;
> EXECUTE perintah INTO result;
> RETURN result;
> END;
> $BODY$
> LANGUAGE plpgsql VOLATILE COST 100;
> ALTER FUNCTION function_birthday(date)
> OWNER TO postgres;

Related

WHERE EXTRACT PostgreSQL

I wrote the following Query that works perfectly while running on excel. But it says that there is a Syntax Error whenever I try to run it on pgAdmin. It says that it's located after the WHERE statement, where it says
WHERE
EXTRACT(YEAR FROM DATE(horasolicitud)) = ?
AND EXTRACT(MONTH FROM DATE(horasolicitud)) = ?
The full query is:
--Consulta del Mes
SELECT
OT.id AS id_ot,
OT.numero AS numero_orden,
OT.idautoridad,
AU.nombre AS nombre_autoridad,
OT.idcarretera,
CR.nombre AS nombre_carretera,
OT.idcliente,
CT.idtipodecliente,
CT.nombre AS nombre_cliente,
CT.numero AS numero_cliente,
OT.idprimeroperador AS idoperador,
OP.nombre AS nombre_operador,
OP.numero AS numero_operador,
OT.idprimerunidad AS idunidad,
UN.modelo AS modelo,
UN.numero AS numero_grua,
UN.placas,
UN.idtipodeunidad,
OT.idsucursal,
SC.nombre AS nombre_sucursal,
OT.idtipodeservicio,
CASE
WHEN OT.idtipodeservicio IN (1,2,3,4,6) THEN 'Remolque'
WHEN OT.idtipodeservicio IN (5) THEN 'Auxilio Vial'
ELSE 'Otro'
END AS TipoServicio,
OT.idusuario,
OT.idvehiculo,
OT.estatus,
OT.horainicio AS fechahora_inicio,
OT.horasalida AS fechahora_salida,
OT.horasolicitud AS fechahora_solicitud,
OT.fechaprogramada AS fecha_programada,
CASE
WHEN DATE(OT.horainicio) < DATE(OT.horasolicitud) THEN '0'
ELSE OT.horainicio - OT.horasolicitud
END AS tiempo_contacto,
CASE WHEN EXTRACT(DAY FROM DATE(OT.fechaprogramada)) > 0 THEN '0' ELSE
(EXTRACT(HOUR FROM (CASE
WHEN DATE(OT.horainicio) < DATE(OT.horasolicitud) THEN '0'
ELSE OT.horainicio - OT.horasolicitud
END)) * 60 +
EXTRACT(MINUTE FROM (CASE
WHEN DATE(OT.horainicio) < DATE(OT.horasolicitud) THEN '0'
ELSE OT.horainicio - OT.horasolicitud
END))) END AS minutos_contacto,
CASE WHEN EXTRACT(DAY FROM DATE(OT.fechaprogramada)) > 0 THEN '0' ELSE
(EXTRACT(HOUR FROM (CASE
WHEN DATE(OT.horasalida) < DATE(OT.horasolicitud) THEN '0'
ELSE OT.horasalida - OT.horasolicitud
END)) * 60 +
EXTRACT(MINUTE FROM (CASE
WHEN DATE(OT.horasalida) < DATE(OT.horasolicitud) THEN '0'
ELSE OT.horasalida - OT.horasolicitud
END))) END AS minutos_asignacion,
DATE(ot.horasolicitud) AS fecha_solicitud,
EXTRACT(YEAR FROM DATE(ot.horasolicitud)) AS anio_solicitud,
EXTRACT(MONTH FROM DATE(ot.horasolicitud)) AS mes_solicitud,
EXTRACT(HOUR FROM (ot.horasolicitud)) AS hora_solicitud,
CASE
WHEN EXTRACT(HOUR FROM (ot.horasolicitud)) > 6
AND EXTRACT(HOUR FROM (ot.horasolicitud)) < 19 THEN 'dia'
ELSE 'noche'
END AS dia_noche,
OT.horatermino AS fechahora_termino,
OT.minutosdecontacto AS minutos_contacto_stma,
OT.iddivision,
DV.nombre AS nombre_division,
OT.ccachesubtotal AS importe_total,
OT.cimportetrafico AS importe_trafico,
OT.longddorigen AS longitud,
OT.latddorigen AS latitud,
OT.cachekminicio AS km_inicio,
OT.cachekmfin AS km_fin,
CASE
WHEN OT.cachekminicio = 0 THEN '0'
ELSE OT.cachekmfin - OT.cachekminicio
END AS km_recorr
FROM OT
LEFT JOIN autoridad AU ON OT.idautoridad = AU.idautoridad
LEFT JOIN carretera CR ON OT.idcarretera = CR.idcarretera
LEFT JOIN cliente CT ON OT.idcliente = CT.id
JOIN operador OP ON OT.idprimeroperador = OP.id
JOIN unidad UN ON OT.idprimerunidad = UN.id
JOIN sucursal SC ON OT.idsucursal = SC.idsucursal
JOIN division DV ON ot.iddivision = DV.id
WHERE
EXTRACT(YEAR FROM DATE(horasolicitud)) = ?
AND EXTRACT(MONTH FROM DATE(horasolicitud)) = ?
AND OT.estatus IN (2, 3, 7)
AND OT.idcliente NOT IN (5115, 4966)
AND OT.idcliente NOTNULL
And the error says:
ERROR: syntax error at or near "AND"
LINE 91: AND EXTRACT(MONTH FROM DATE(horasolicitud)) = ?
^
SQL state: 42601
Character: 3006
I would very much appreciate your help. Thank you.

Stored procedure get stuck after move database

I just dump data from production server to my local server for testing purpose. Our app uses a stored procedure with about 300 lines of sql. This procedure work fine in the server database, but it got stuck (running forever) every times i run it on my local database. Does anyone have any ideas about why it got stuck.
This is my command to dump data.
pg_dump --host localhost --port 5432 --username postgres --dbname test-new >D:\test5.sql
psql --host localhost --port 5432 --username postgres --dbname test-qa < file.sql
here is the Store Procedure
CREATE OR REPLACE FUNCTION public.insert_hm_ticket_statistic(v_sprint_id bigint)
RETURNS integer
LANGUAGE plpgsql
AS $$
DECLARE
v_ticket INT;
v_startsprint_date DATE;
v_end_date DATE;
v_current_date DATE;
v_first_activity_date DATE;
v_started DATE;
v_sprint_setting VARCHAR(255);
v_time_spent_second FLOAT;
v_remaining_estimate FLOAT;
v_time_logged_tmp FLOAT;
v_has_log INT;
v_time_logged_tk FLOAT;
v_oe_tk INT;
v_has_past_sprint INT;
v_oe_sprint INT;
v_complete_of_sprint FLOAT;
v_oe_tk_burnt FLOAT;
v_oe_sprint_burnt FLOAT;
v_project_complete FLOAT;
v_complete_tk FLOAT;
rl_cursor CURSOR FOR SELECT
tk.id,
tk.has_past_sprint,
cast(first_activity_date AS DATE)
FROM hm_ticket tk
WHERE sprint = v_sprint_id AND deleted = 0;
BEGIN
-- find start date and end date of sprint
SELECT
cast(start_date AS DATE),
cast(end_date AS DATE)
INTO v_startsprint_date, v_end_date
FROM hm_sprint
WHERE id = v_sprint_id AND status <> 'future';
-- find sprint setting
IF NOT exists(SELECT d.burn_down_statuses
FROM hm_sprint x, hm_setting c, hm_burn_down_status d
WHERE c.id = d.setting AND x.setting = c.id AND x.id = v_sprint_id)
THEN
v_sprint_setting :='xxx';
ELSE
SELECT string_agg(d.burn_down_statuses, ',')
INTO v_sprint_setting
FROM hm_sprint x, hm_setting c, hm_burn_down_status d
WHERE c.id = d.setting AND x.setting = c.id AND x.id = v_sprint_id;
END IF;
raise notice 'v_sprint_setting %', v_sprint_setting;
OPEN rl_cursor;
LOOP
FETCH rl_cursor INTO v_ticket, v_has_past_sprint, v_first_activity_date;
raise notice 'v_ticket: %', v_ticket;
EXIT WHEN NOT FOUND;
/*select cast(min(started) as date) into v_started
from hm_worklog
where ticket=v_ticket and cast(started as date) between v_startsprint_date and v_end_date;
if v_started is null then v_current_date:=v_startsprint_date;
else
v_current_date:=v_started;
end if;*/
v_current_date:=v_startsprint_date;
--- calculate remaining estimate, time logged of ticket
IF v_has_past_sprint = 0
THEN
SELECT
coalesce(remaining_estimate, 0),
coalesce(time_logged, 0)
INTO v_remaining_estimate, v_time_logged_tk
FROM hm_ticket
WHERE id = v_ticket;
ELSE
SELECT coalesce(time_logged, 0)
INTO v_time_logged_tmp
FROM hm_ticket
WHERE id = v_ticket;
--------------------------------------
SELECT
coalesce(remaining_estimate, 0),
v_time_logged_tmp - coalesce(time_logged, 0)
INTO v_remaining_estimate, v_time_logged_tk
FROM hm_ticket_past_sprint
WHERE ticket = v_ticket;
END IF;
raise notice '----------v_has_past_sprint: %', v_has_past_sprint;
raise notice '----------v_time_logged_tmp: %', v_time_logged_tmp;
raise notice '----------v_time_logged_tk: %', v_time_logged_tk;
raise notice '----------v_remaining_estimate: %', v_remaining_estimate;
-- calculate oe of ticket
IF v_has_past_sprint = 0
THEN
SELECT cast(CASE WHEN coalesce(original_estimate, 0) = 0
THEN coalesce(time_logged, 0)
ELSE original_estimate
END
AS FLOAT)
INTO v_oe_tk
FROM hm_ticket
WHERE id = v_ticket;
ELSE
SELECT coalesce(time_logged, 0)
INTO v_time_logged_tmp
FROM hm_ticket
WHERE id = v_ticket;
--------------------------------------
SELECT cast(CASE WHEN coalesce(original_estimate, 0) = 0
THEN v_time_logged_tmp - coalesce(time_logged, 0)
ELSE original_estimate
END
AS FLOAT)
INTO v_oe_tk
FROM hm_ticket_past_sprint
WHERE ticket = v_ticket;
END IF;
raise notice 'v_oe_tk: %',v_oe_tk;
/*########################################################################## START TO LOOP CURRENT DATE #############################################################################*/
WHILE v_current_date <= v_end_date LOOP
--- calculate time_spent_seconds from start sprint
IF NOT exists(SELECT id
FROM hm_worklog
WHERE ticket = v_ticket AND cast(started AS DATE) BETWEEN v_startsprint_date AND v_current_date)
THEN
v_time_spent_second:=0;
ELSE
SELECT cast(sum(time_spent_seconds) AS FLOAT)
INTO v_time_spent_second
FROM hm_worklog
WHERE ticket = v_ticket AND cast(started AS DATE) BETWEEN v_startsprint_date AND v_current_date
GROUP BY ticket;
END IF;
raise notice 'v_time_spent_second: %', v_time_spent_second;
--calculate % complete of ticket/day
IF NOT v_current_date = v_end_date THEN
IF NOT exists(SELECT date FROM hm_ticket_history WHERE ticket = v_ticket AND cast(date AS DATE) = v_current_date)
then
-- FIND STATUS OF TICKET IN SETTING. 0: NO STATUS EXIST -> FORMULAR SHOULD BE APPLIED , <>0 : EXIST--> SET COMPLETE TK = 0
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket
WHERE id = v_ticket;
ELSE
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket_history
WHERE ticket = v_ticket AND cast("date" AS DATE)= v_current_date;
END IF;
ELSE
--NOTE: IF V_CURRENT_DATE == END-DATE-OF-SPRINT, COMPLETE % WILL BE CALCULATED BASE ON LATEST TICKET STATUS, NOT LAST-DAY-OF-SPRINT TICKET STATUS
IF NOT exists(SELECT date FROM hm_ticket_history WHERE ticket = v_ticket AND cast(date AS DATE) = v_current_date)
then
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket
WHERE id = v_ticket;
else
SELECT CASE WHEN (position(upper(trim(status)) IN upper(trim(v_sprint_setting))) = 0)
THEN CASE WHEN v_remaining_estimate = 0 AND v_time_logged_tk <> 0 THEN 80
WHEN v_remaining_estimate = 0 AND v_time_logged_tk = 0 THEN 0
WHEN (v_remaining_estimate + v_time_logged_tk) = 0 THEN 0
ELSE round(cast(v_time_spent_second * 100 / (v_time_logged_tk + v_remaining_estimate) AS NUMERIC), 2)
END
ELSE 100
END AS complete
INTO v_complete_tk
FROM hm_ticket_history
WHERE ticket = v_ticket order by date desc limit 1;
END IF;
END IF;
if v_complete_tk > 100 then v_complete_tk := 100;
end if;
raise notice 'v_sprint_setting: %', v_sprint_setting;
raise notice 'v_complete_tk: %', v_complete_tk;
raise notice '---------------------------------';
-- check has log
IF exists(SELECT id
FROM hm_worklog
WHERE cast(started AS DATE) = cast(v_current_date AS DATE) AND ticket = v_ticket)
THEN
v_has_log := 1;
ELSE
v_has_log := 0;
END IF;
--raise notice 'v_has_log: %', v_has_log;
-- calculate oe of sprint
SELECT sum(x.oe)
INTO v_oe_sprint
FROM
(
SELECT CASE WHEN coalesce(original_estimate, 0) = 0
THEN coalesce(time_logged, 0)
ELSE coalesce(original_estimate, 0)
END oe
FROM hm_ticket
WHERE sprint = v_sprint_id AND cast(first_activity_date AS DATE) <= v_current_date
AND has_past_sprint = 0
UNION ALL
SELECT CASE WHEN coalesce(b.original_estimate, 0) = 0
THEN coalesce(a.time_logged - b.time_logged)
ELSE coalesce(b.original_estimate, 0)
END oe
FROM hm_ticket a, hm_ticket_past_sprint b
WHERE a.id = b.ticket AND a.sprint = v_sprint_id AND cast(a.first_activity_date AS DATE) <= v_current_date
AND a.has_past_sprint = 1
) x;
-- raise notice 'v_oe_sprint: %', v_oe_sprint;
-- calculate v_oe_tk_burnt
SELECT CASE WHEN v_time_spent_second = 0 OR v_oe_tk = 0
THEN 0
ELSE round(cast((v_time_spent_second * 100 / v_oe_tk) AS NUMERIC), 2)
END
INTO v_oe_tk_burnt;
--raise notice 'v_oe_tk_burnt: %', v_oe_tk_burnt;
-- calculate v_oe_sprint_burnt
IF v_oe_sprint = 0
THEN
v_oe_sprint_burnt:=100;
ELSE
SELECT round(cast((v_time_spent_second * 100 / v_oe_sprint) AS NUMERIC), 2)
INTO v_oe_sprint_burnt;
END IF;
--raise notice 'v_oe_sprint_burnt: %', v_oe_sprint_burnt;
-- calculate v_project_complete
IF v_oe_sprint = 0
THEN
v_project_complete:=100;
ELSE
SELECT round(cast((v_complete_tk * v_oe_tk / v_oe_sprint) AS NUMERIC), 2)
INTO v_project_complete;
END IF;
-- raise notice 'v_project_complete: %', v_project_complete;
IF v_current_date >= v_first_activity_date
THEN
INSERT INTO hm_ticket_statistic (complete, date, has_log, last_modified, original_estimate_burnt, original_estimate_project_burnt, project_complete, status, ticket, sprint)
VALUES
(v_complete_tk, cast(v_current_date AS DATE), v_has_log, current_timestamp, v_oe_tk_burnt, v_oe_sprint_burnt,
v_project_complete, 1, v_ticket, v_sprint_id)
ON CONFLICT (date, ticket, sprint)
DO UPDATE
SET complete = v_complete_tk,
has_log = v_has_log,
original_estimate_burnt = v_oe_tk_burnt,
original_estimate_project_burnt = v_oe_sprint_burnt,
project_complete = v_project_complete;
END IF;
v_current_date:= v_current_date + INTERVAL '24 hours';
EXIT WHEN NOT found;
END LOOP;
END LOOP;
CLOSE rl_cursor;
RETURN 0;
END;
Also, if you see anything that can be improved in the code, please suggest me.
Try running analyze on the local database, after restoring the dump. This updates statistics.
Finally found the bug. It is a deadlock bug, i used Synchronized on function way too much, they start to get stuck. The production server still get the same problem, i just don't see it. So i try to use Synchronized more selectively, reduce the size of functions that Synchronized on. Then it is fixed.

How to use part of a query inside a variable Oracle Function

I'm trying to use a part of a query into a variable , because I have many ifs to prepare the query , but I have not used something like this.
FUNCTION f_rel_vendas_importacao(vTP_DADOS in varchar2, nCODIGO in number, dDT_COMPRA_INI in DATE, dDT_COMPRA_FIM in DATE, dDT_EFETIVACAO_INI in DATE, dDT_EFETIVACAO_FIM in DATE) RETURN number is
nRetorno number(14,2);
vSTRING VARCHAR2(2000);
begin
IF vTP_DADOS = 'VL_COMISSAO' THEN
vSTRING := 'SUM( DECODE( CPF.CD_MOEDA, 1, CPF.VL_COTACAO_UNIT * CPF.QTDE_COMPRA, ( SELECT Imp_Pack.fu_converte_moeda_ORACLE( CPF.CD_MOEDA, 1, CDT.DT_RECEBIMENTO, CPF.VL_COTACAO_UNIT, 1) * CPF.QTDE_COMPRA FROM dual ) ) )';
END IF;
IF vTP_DADOS = 'QTD_VENDA_SELECTCHEMIE_PERIODO' THEN
vSTRING := 'count(*)';
END IF;
SELECT
vSTRING
INTO
nRetorno
FROM
COMPRA_PROD_FORN CPF,
COMPRA_DATA CDT
WHERE
(CDT.DT_RECEBIMENTO >= dDT_COMPRA_INI AND CDT.DT_RECEBIMENTO <= dDT_COMPRA_FIM) AND
CDT.CD_COMPRA = CPF.CD_COMPRA AND
CDT.CD_TP_DATA = 7 AND
CPF.CD_FORNECEDOR = nCODIGO;
Return nRetorno;
end
f_rel_vendas_importacao;
When you SELECT vString, the result is the content of the variable vString. It doesn't make any attempt to interpret that content as a column or expression. You are best off placing those expressions directly into the query.
IF vTP_DADOS = 'VL_COMISSAO' THEN
SELECT
SUM( DECODE( CPF.CD_MOEDA, 1,
CPF.VL_COTACAO_UNIT * CPF.QTDE_COMPRA,
( SELECT Imp_Pack.fu_converte_moeda_ORACLE( CPF.CD_MOEDA, 1,
CDT.DT_RECEBIMENTO, CPF.VL_COTACAO_UNIT, 1) *
CPF.QTDE_COMPRA
FROM dual ) ) )
INTO
nRetorno
FROM
COMPRA_PROD_FORN CPF,
COMPRA_DATA CDT
WHERE
(CDT.DT_RECEBIMENTO >= dDT_COMPRA_INI AND
CDT.DT_RECEBIMENTO <= dDT_COMPRA_FIM) AND
CDT.CD_COMPRA = CPF.CD_COMPRA AND
CDT.CD_TP_DATA = 7 AND
CPF.CD_FORNECEDOR = nCODIGO;
END IF;
IF vTP_DADOS = 'QTD_VENDA_SELECTCHEMIE_PERIODO' THEN
SELECT count(*)
INTO
nRetorno
FROM
COMPRA_PROD_FORN CPF,
COMPRA_DATA CDT
WHERE
(CDT.DT_RECEBIMENTO >= dDT_COMPRA_INI AND
CDT.DT_RECEBIMENTO <= dDT_COMPRA_FIM) AND
CDT.CD_COMPRA = CPF.CD_COMPRA AND
CDT.CD_TP_DATA = 7 AND
CPF.CD_FORNECEDOR = nCODIGO;
END IF;

Adding a count of values

Is there another way I can sum up counts with less code?
I'm using a view (my only option) to try to find out if a customer spent money during any two of the last 5 calendar years
Table name:
V_PERSON
V_REVENUE
Columns:
V_PERSON.ID
V.REVENUE.PersonID
V.REVENUE.Year1 revenue for the year (currently 2016)
V.REVENUE.Year2 revenue for the year (currently, 2015)
V.REVENUE.Year3
V.REVENUE.Year4
V.REVENUE.Year5
Here's what I've tried:
SELECT V_PERSON.ID
FROM V_PERSON
WHERE
(
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year1 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year2 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year3 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year4 > 0
)
+
(
SELECT '1'
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID
AND V_REVENUE.Year5 > 0
)
) >= 2
Here's one option using exists with multiple case statements:
select id
from person p
where exists (
select 1
from revenue r
where p.id = r.personid
and case when r.year1 > 0 then 1 else 0 end +
case when r.year2 > 0 then 1 else 0 end +
case when r.year3 > 0 then 1 else 0 end +
case when r.year4 > 0 then 1 else 0 end +
case when r.year5 > 0 then 1 else 0 end >= 2
)
How about a CASE statement:
SELECT V_PERSON.ID
FROM V_PERSON
WHERE
(
SELECT (case when V_REVENUE.Year1 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year2 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year3 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year4 > 0 then 1 else 0 end) +
(case when V_REVENUE.Year5 > 0 then 1 else 0 end)
FROM V_REVENUE
WHERE V_REVENUE.PersonID = V_PERSON.ID) >= 2

Pervasive sql to Oracle

I am having trouble converting this Pervasive sql query to Oracle. The errors that oracle is giving me does not help. It is giving me an error at SQL_Date.
This is what I have in Pervasive:
SELECT
(CASE
WHEN joefdt = 0
THEN NULL
WHEN joefdt > 0
THEN CONVERT(LEFT(CONVERT(joefdt, SQL_CHAR),4) + '-' + RIGHT(LEFT(CONVERT(joefdt, SQL_CHAR),6),2) + '-' + RIGHT(CONVERT(joefdt, SQL_CHAR),2),SQL_DATE) END) AS EFFECTIVEDATE,
(CASE
WHEN jopost = 0
THEN NULL
WHEN jopost > 0
THEN CONVERT(LEFT(CONVERT(jopost, SQL_CHAR),4) + '-' + RIGHT(LEFT(CONVERT(jopost, SQL_CHAR),6),2) + '-' + RIGHT(CONVERT(jopost, SQL_CHAR),2),SQL_DATE) END) AS POSTDATE,
(SELECT ltrim(rtrim(cdname)) from money.code WHERE cdtabl = 3 AND cdnumb = joetyp) AS TYPE,
(SELECT ltrim(rtrim(cdname)) from money.code WHERE cdtabl = 5 AND cdnumb = jodelm) AS DELIVERYMETHOD,
joissd AS SHARESISSUED, jocand AS SHARESCANCELLED , joprsn AS BROKERID, joprsn AS TRANSACID
FROM money.jour
WHERE joiss = 1 AND joetyp in (2,3,4) AND (JOISSD > 0 OR JOCAND > 0)
AND joefdt >= '19920127' AND joefdt <= '20040726'
ORDER BY joefdt;
This is what I have tried, but it doesn't work:
SELECT
(CASE
WHEN joefdt = 0
THEN NULL
WHEN joefdt > 0
THEN CONVERT(substr(CONVERT(joefdt, SQL_CHAR),4) + '-' + RIGHT(LEFT(CONVERT(joefdt, SQL_CHAR),6),2) + '-' + RIGHT(CONVERT(joefdt, SQL_CHAR),2),SQL_DATE) END) AS EFFECTIVEDATE,
(CASE
WHEN jopost = 0
THEN NULL
WHEN jopost > 0
THEN CONVERT(substr(CONVERT(jopost, SQL_CHAR),4) + '-' + RIGHT(LEFT(CONVERT(jopost, SQL_CHAR),6),2) + '-' + RIGHT(CONVERT(jopost, SQL_CHAR),2),SQL_DATE) END) AS POSTDATE, ----Error at SQL_DATE
(SELECT ltrim(rtrim(cdname)) from money.code WHERE cdtabl = 3 AND cdnumb = joetyp) AS TYPE,
(SELECT ltrim(rtrim(cdname)) from money.code WHERE cdtabl = 5 AND cdnumb = jodelm) AS DELIVERYMETHOD,
joissd AS SHARESISSUED, jocand AS SHARESCANCELLED , joprsn AS BROKERID, joprsn AS TRANSACID
FROM money.jour
WHERE joiss = 1 AND joetyp in (2,3,4) AND (JOISSD > 0 OR JOCAND > 0)
AND joefdt >= '20000302' AND joefdt <= '20000302'
ORDER BY joefdt;
In Oracle CONVERT function translates character string from one character set to another. It cannot be used to convert something to date (does Pervasive means this?) or something. Oracle does not know identifiers SQL_DATE and SQL_CHAR, so you cannot use them in this manner. And last, conditions like joefdt >= '20000302' are doubtful. Maybe it means something like joefdt >= DATE '2000-03-02'