Reputation: 45
I have here simple query using group function.Here is the query
SELECT DECODE (DIRAPP, NULL, 'SML', DIRAPP) DD
FROM (SELECT 'At Director Approval '
|| NVL (COUNT (*), 0)
|| ' Cheques of Rs. '
|| NVL (TO_CHAR (SUM (BPV_AMT), '9,999,999,999'), 0)
|| ' in '
|| CONCATENATE_LIST
(CURSOR (SELECT DISTINCT NVL
(BPV_DTE,
SYSDATE
) BPV_DTE
FROM CHECK_DATA
WHERE STA_FLG IN (1, 3)
ORDER BY 1 DESC
)
) DIRAPP
FROM CHECK_DATA
WHERE STA_FLG IN (1, 3)
GROUP BY 1, 2) A
I have used the nvl function and also decode but when no data found against the flags 1 and 3 then nothing is shown even 0
from nvl and also working decode.I want to show the whole string with as At Director Approval 0 Cheques of Rs.0
Please any one help me to do this
Upvotes: 0
Views: 2054
Reputation: 191275
decode
isn't broken, it just has no data to work with. You are filtering on where sta_flg in (1,3)
, so if there are no records with either status, there are no rows at all. You can't decode what doesn't exist.
One way around this is to change the way you're counting and summing the values so that the filtering is effectively done within the select
, not the where
. Removing the formatting for a moment, rather than doing:
SELECT COUNT(*), SUM(BPV_AMT)
FROM check_data
WHERE sta_flag IN (1,3);
... which will return no rows if there are no records with matching flags, even if there is other data in the table, you can do:
SELECT SUM(CASE WHEN sta_flg IN (1,3) THEN 1 ELSE 0 END) AS rec_cnt,
SUM(CASE WHEN sta_flg IN (1,3) THEN bpv_amt ELSE 0 END) AS bpv_amt_tot
FROM check_data;
As long as the table isn't empty, this will return a single row of data, with either normal values or both rec_cnt
and bpv_amt_tot
set to zero.
Plugging that in as an inner select your query might look like:
SELECT 'At Director Approval '
|| rec_cnt
|| ' Cheques of Rs. '
|| TO_CHAR(bpv_amt_tot, '9,999,999,999')
|| CASE WHEN rec_cnt = 0 THEN NULL
ELSE ' in ' || CONCATENATE_LIST(CURSOR(
SELECT DISTINCT NVL(bpv_dte, SYSDATE)
FROM check_data
WHERE sta_flg IN (1, 3)
ORDER BY 1 DESC
)) END AS dirapp
FROM (
SELECT SUM(CASE WHEN sta_flg IN (1,3) THEN 1 ELSE 0 END) AS rec_cnt,
SUM(CASE WHEN sta_flg IN (1,3) THEN bpv_amt ELSE 0 END) AS bpv_amt_tot
FROM check_data
);
The case
around the ' in ' || CONCATENATE_LIST(...
part is just to avoid a trailing in
appearing when there are no matching statuses.
Since you aren't selecting any non-aggregated columns, you don't need a group by
clause. (And the one you had was incorrect anyway - you can't group by column positions, so group by 1,2
is grouping by two constant values, which doesn't add anything).
And finally, since you're using concatenate_list()
I assume you're on a version earlier than 11gR2; if you are on the current version then the built-in listagg()
would be simpler.
Upvotes: 3