SQL*Plus Custom Summary Report - oracle

I have a requirement to generate the following summary report that look like the following:
My problem is that,
I have no idea on how do I fill the count data in this custom report.
I do not know how to put it in a table view like the above in a text document. It is not HTML.
So far, I only know how to do the first row, and column without the table view.
Here are my codes.
SET HEADING OFF;
SET LINESIZE 200;
SET SPACE 0;
SET ECHO OFF;
SET FEEDBACK OFF;
SET VERIFY OFF;
SET MARKUP HTML OFF SPOOL OFF;
SET TERMOUT OFF; --Do not show output to the screen.
SET NEWPAGE NONE; --Remove the first blank line at the top of the page and between queries.
TTITLE LEFT "REPORT NAME" RIGHT "PAGE : " SQL.PNO SKIP 1 -
LEFT "--------------------------------" RIGHT "DATE : " _DATE SKIP 1 -
LEFT "A) TOTAL RECORDS " RIGHT total_records; -- Cannot output variable in the title.
LEFT "B) MATCHED RECORDS " RIGHT matched_records; -- Cannot output variable in the title.
LEFT "C) UNMATCHED RECORDS " RIGHT matched_records; -- Cannot output variable in the title.
BTITLE LEFT "E N D";
total_records is an insert into statement.
SELECT COUNT(*) INTO total_records FROM TABLE;
I have not done matched records and unmatched records. But the only way I can think of
Select a statement into a cursor.
Loop into the cursor.
Increase matched count when there is a match.
Once loop finish. unmatched count = total count - matched count.
I don't think this is the most efficient way. But, if you have a better way, let me know.

Does something like this ring a bell? Example is based on Scott's sample schema:
SQL> select 'Total records' name, count(*) cnt
2 from emp
3 union all
4 select 'Matched count', sum(case when deptno = 10 then 1 else 0 end)
5 from emp
6 union all
7 select 'Unmatched count', sum(case when deptno = 10 then 0 else 1 end)
8 from emp;
NAME CNT
--------------- ----------
Total records 14
Matched count 3
Unmatched count 11
SQL>

Related

Oracle SQL Spool Output Issues - Headers and Dashes

Good day, Stack Overflow folks. I have a question regarding some SQL code that I'm updated for some regulatory processes that my team has. When I run the following code, I get the export set up just fine, however, I am getting several header rows and several rows of nothing. The SQL code in question is below:
Set Heading On
Set Colsep '|'
Set NumFormat 999999999999.99
Set Echo Off
Spool 'X:\Cool\Drive\Space\Yo\Output.csv' Replace;
Select …
From …
Group By …
;
Spool Off;
The output looks something like this:
A| B| C|...
-|-------|------|...
with multiple instances of those rows repeating.
Does anyone out there know how to stop this from happening, and how I can trim the outputs so we don't have a bunch of white spaces before the actual data starts printing?
Thank you!
You need to add two things
SQL> set underline off
SQL> set pagesize 100
PAGESIZE says, how many rows to print before you print the header column names again. If you only want to see those once, set the pagesize larger than the number of rows.
Here's my query -
SQL> set heading on
SQL> set colsep '|'
SQL> set numformat 999999999999.99
SQL> select sum(salary), department_id
2 from employees
3 group by department_id
4 ;
And if I run that -
SUM(SALARY)| DEPARTMENT_ID
105970.33| 100.00
51214.47| 30.00
14380.48|
119020.33| 90.00
39014.85| 20.00
20532.81| 70.00
41680.87| 110.00
321867.32| 50.00
626338.39| 80.00
13355.08| 40.00
59187.52| 60.00
8228.13| 10.00
12 rows selected.

SqlPlus (Oracle) Spool Formatting Issue

I have scheduled a shell script which is outputting the following email. I want to remove the unwanted/additional duplicated text which is being printed using the dual table below to give a heading to my SQL select output.
How can I do it?
Following is the spool SQL script. After the script execution is done (/home/oracle/MFS_ALERT/PGW_ALERTS_FRAUDS/PGW_ALERTS.out) file is added to the email body and sent to recipients.
Can you guide which set parameter command is missing OR which one is extra or unnecessary below?
This is shell script file code.
sqlplus user/pass#pgwdb #/home/oracle/MFS_ALERT/PGW_ALERTS_FRAUDS/PGW_ALERTS.sql
sleep 5
/bin/mail -s "MFS PGW Fraud Alerts (Day)" -r “test-email-1#email-domain.com” "test-email-2#email-domain.com" < /home/oracle/MFS_ALERT/PGW_ALERTS_FRAUDS/PGW_ALERTS.out
PGW_ALERTS.sql Code
set echo off;
set feedback off ;
set verify off ;
set serveroutput off;
set heading on;
set trimspool on;
set headsep off;
set PAGESIZE 60;
set LINESIZE 400;
SET WRAP OFF;
SET COLSEP ' ';
set numw 20;
SPOOL /home/oracle/MFS_ALERT/PGW_ALERTS_FRAUDS/PGW_ALERTS.out append;
select '====== Transactions with count > 2 from same MSISDN ======' from dual;
SELECT '"'
|| MOBILENUMBER
|| '"' MSISDN,
AMOUNT/100 AMOUNT,
DECODE(TXNTYPEID,'6','MW', '0') TXN_TYPE,
MERCHANTCODE,
COUNT (*) COUNT
FROM TBL_TXN_LOG
WHERE TXNTYPEID ='6'
AND AMOUNT <=10000
AND TXNDATETIME>= SYSDATE -1
AND STATUS ='xxxx'
GROUP BY '"'
|| MOBILENUMBER
|| '"', AMOUNT/100, DECODE(TXNTYPEID,'6','MW', '0'), MERCHANTCODE
HAVING COUNT (*) > 2
UNION ALL
SELECT '"'
|| MOBILENUMBER
|| '"' MSISDN ,
AMOUNT/100 AMOUNT,
DECODE(TXNTYPEID,'164', 'Card', '0') TXN_TYPE,
MERCHANTCODE,
COUNT (*) COUNT
FROM TBL_TXN_LOG
WHERE TXNTYPEID ='164'
AND AMOUNT >=2500000
AND TXNDATETIME>= SYSDATE - 1
AND STATUS ='xxxx'
GROUP BY MOBILENUMBER,
AMOUNT,
DECODE(TXNTYPEID,'164','Card', '0') ,
MERCHANTCODE
HAVING COUNT (*) > 1
;
SPOOL OFF;
SET DEFINE ON
SET SERVEROUTPUT OFF
quit
The email which recipient is getting.,
-----Original Message----- From: destination.email#emaildomain.com Sent: Friday, December 8, 2017 7:36 PM To:
destination.email#emaildomain.com Subject: MFS PGW Fraud Alerts (4
Hourly)
***> '======TRANSACTIONSWITHAMOUNT<100FORMW&>25000======'
--------------------------------------------------------------***
====== Transactions with Amount < 100 for MW & > 25000 ======
MSISDN AMOUNT TXN_ MERCHANTCODE
COUNT
---------------------- -------------------- ---- ------------------------------ -------------------- "924008482888" 70 MW 00342386 1
"924008345433" 20 MW 002218387
1
I want to remove these extra lines
'======TRANSACTIONSWITHAMOUNT<100FORMW&>25000======'
Change your query a bit, use an alias for your heading, and turn off/on heading as shown:
set heading off
select '====== Transactions with count > 2 from same MSISDN ======' as info from dual;
select '<pre>' from dual;
set heading on
-- rest of your query
set heading off
select '</pre>' from dual;
That should do the trick if the message is being sent in HTML format.

Unreadable character in generated sqlplus file

I have a shell with one command line opening sql plus and calling a sql file
$ORACLE_HOME/bin/sqlplus id/psw #SQL_DIRECTORY/myfile.sql
in this file I write this :
spool myfile.csv
select 'column 01', ';', 'column 02' from dual;
select myColumn1, ';', mycolum2 from mytable
spool off
It works good BUT on the first line of the the first column of each select there is a special character.
Why is that? how can I get rid of this
Thanks
From the description it sounds like you have a login.sql or glogin.sql user profile that is issuing set newpage 0:
Sets the number of blank lines to be printed from the top of each page to the top title. A value of zero places a formfeed at the beginning of each page (including the first page) and clears the screen on most terminals. If you set NEWPAGE to NONE, SQL*Plus does not print a blank line or formfeed between the report pages.
In Excel that does show up as an unprintable character with a question mark in a small square; in Notepad++ it seems to show as FF in reverse colouring; and in some editors (e.g. Vim) it shows as ^L. This is the ASCII form feed character, decimal 12 or 0xC.
You can either reset that with set newpage none, or make it irrelevant with set pagesize 0, which has the convenient side effect of removing the column headers and separators. You may also want to set feedback off if you aren't already.
Samples with contrasting settings:
set newpage 0;
set feedback on;
set pagesize 100;
spool ctrl.csv
select 'head 1;head 2' from dual;
select sysdate, ';', systimestamp from dual;
spool off
^L'HEAD1;HEAD2'
-------------
head 1;head 2
1 row selected.
^LSYSDATE ' SYSTIMESTAMP
------------------- - ---------------------------------------------------------------------------
2015-09-16 15:45:42 ; 16-SEP-15 15.45.42.333627 +01:00
1 row selected.
And
set newpage none;
set feedback off;
set pagesize 0;
spool ctrl.csv
select 'head 1;head 2' from dual;
select sysdate, ';', systimestamp from dual;
spool off
head 1;head 2
2015-09-16 15:46:11 ; 16-SEP-15 15.46.11.274863 +01:00

SQL*Plus Spool Oracle ( Subquery /With Clause Issue)

Can you please help me ?
when I execute the .sql file below in Toad, it gives me the expected results.
with
a as(select extract(year from sysdate)var_year,to_char(sysdate,'mm-dd')var_day from dual),
b as(select case when var_day between '10-01'and '12-31'
then to_date(var_year||'-10-01','yyyy-mm-dd')
else to_date(var_year-1||'-10-01','yyyy-mm-dd')end d1,
case when var_day between'10-01'and'12-31'
then to_date(var_year+1||'-09-30','yyyy-mm-dd')
else to_date(var_year||'-09-30','yyyy-mm-dd')end d2
from a)
select * from b,SCHEMA.TABLE1
where SCHEMA.TABLE1.DATE_FRAIS between b.d1 and b.d2;
But when I Try to launch it using a .cmd job adding a spool function, the console opens but nothing happens and the console stay open. The .csv file is generated but nothing inside.
Please find below Script not working (spool succeeded but without content):
SET FEEDBACK OFF
set heading on
SET PAGESIZE 0
SET LINESIZE 8000
set pagesize 50000
SET COLSEP ";"
COLUMN dcol new_value mydate noprint
select to_char(sysdate,'YYYY_MM_DD') dcol from dual;
SPOOL test.csv;
with
a as(select extract(year from sysdate)var_year,to_char(sysdate,'mm-dd')var_day from dual),
b as(select case when var_day between '10-01'and '12-31'
then to_date(var_year||'-10-01','yyyy-mm-dd')
else to_date(var_year-1||'-10-01','yyyy-mm-dd')end d1,
case when var_day between'10-01'and'12-31'
then to_date(var_year+1||'-09-30','yyyy-mm-dd')
else to_date(var_year||'-09-30','yyyy-mm-dd')end d2
from a)
select * from b,SCHEMA.TABLE1
where SCHEMA.TABLE1.DATE_FRAIS between b.d1 and b.d2;
SPOOL OFF
Whereas, when I launch a "simple" .SQL file by a .cmd job adding a spool function, it works (maybe because I removed "CASE" ?).The .csv file is generated and there is content inside
Please find below an example of Script working (spool succedeed with content) :
SET FEEDBACK OFF
set heading on
SET PAGESIZE 0
SET LINESIZE 8000
set pagesize 50000
SET COLSEP ";"
COLUMN dcol new_value mydate noprint
select to_char(sysdate,'YYYY_MM_DD') dcol from dual;
SPOOL test.csv;
with
a as (select extract(year from sysdate) var_year1, extract(year from sysdate) var_year2, to_char(sysdate) var_day from dual)
select * from a;
SPOOL OFF
I suspect that (a) you've run this as sqlplus -s user/pass #script and don't have an exit at the end of your script, which will cause the command window to stay open; and (b) you don't have any committed data in your table for this year's date range. You would see that effect if you added data in your Toad session and ran your query there, but did not commit those changes - the newly-inserted data would not be visible to any other session in that case, so your SQL*Plus query wouldn't see it. And since you have feedback off, you wouldn't even see 'no rows selected`.
#boneist's simplification is cleaner and simpler than mine, but I'll leave this to show the CTE and non-CTE, and the between and >=/< variations.
Incidentally, you can simplify your date calculation quite a bit, to something like:
with b as (
select add_months(trunc(sysdate, 'YYYY'),
case when extract(month from sysdate) < 10 then -3 else 9 end) d1,
last_day(add_months(trunc(sysdate, 'YYYY'),
case when extract(month from sysdate) < 10 then 8 else 20 end)) d2
from dual
)
select *
from b
join table1 on table1.date_frais between b.d1 and b.d2;
You can see the start and end dates the CTE would generate for various dates with this demo. I think that's what you're after, if I've interpreted your current query properly. (And here is the same query with #boneist's simplification).
Or if you don't really want to show the date range as well as the actual data from table1, move the calculation into the filter:
select * -- but still better to list the columns
from table1
where date_frais >= add_months(trunc(sysdate, 'YYYY'),
case when extract(month from sysdate) < 10 then -3 else 9 end)
and date_frais < add_months(trunc(sysdate, 'YYYY'),
case when extract(month from sysdate) < 10 then 9 else 21 end);
I've also changed this version from between to use >= and <, and pushed the end-date out by a day; that will include any values on the last day of the final month which have a time after midnight (which I see #boneist also commented on). If your dates are all midnight then between would work, but I still prefer this explicit pattern, and it makes the month adjust calculation a little more obvious too I think.
Could it be simply that your query takes a long time to retrieve all the results, and you haven't left it long enough? You might see results in Toad, but have you tried going to the end of the resultset, rather than just getting the first 500 rows (or however many you have set Toad to retrieve per fetch).
I doubt the issue is anything to do with the WITH clause. In any case, there is no need for it; you can simply manipulate sysdate like so, in order to get your results:
select *
from SCHEMA.TABLE1 t1
where t1.DATE_FRAIS between add_months(trunc(add_months(sysdate, 3), 'yyyy'), -3)
and add_months(trunc(add_months(sysdate, 3), 'yyyy'), 9) -1;
N.B. I hope your DATE_FRAIS column has no time elements to it, otherwise you'll be missing anything that's after midnight on the 30th September of each year.

How to create a user entered query search

I am trying to create a report that produces rentals for tools, as its required to be interactive, i'd like the user to be able to enter the partial name of a tool or full name to bring up all the rentals for that tool.
TTITLE CENTER ==================== SKIP 1-
CENTER 'U T O O L' skip 1-
CENTER ==================== SKIP 1 -
LEFT 'Rental Report ' SKIP 1 -
LEFT ============ SKIP 2-
RIGHT 'Page:' -
FORMAT 999 SQL.PNO SKIP 2
set pagesize 50
column MEMBERNAME HEADING 'Member Name' format a20
column TOTAL HEADING 'Total Cost' format L9,999.99
compute sum label 'Total Cost: ' of TOTAL on MEMBERNAME
Break on Rental_ID on Member_ID on MEMBERNAME on Member_ID on Tel SKIP 1
select Member.Member_ID, SUBSTR(Member.FName,0,10) || SUBSTR(' ',0,10) ||
SUBSTR(Member.SName,0,15) as MEMBERNAME, Member.Tel,
Rental.Rental_ID,
Tool.Name,
Rental.DateOut,
Rental.DateIn,
Rental_Line.Qty,
Rental_Line.Price,
Rental_Line.Qty*Rental_Line.Price as TOTAL
from Rental_Line
INNER JOIN Rental
on Rental.Rental_ID = Rental_Line.Rental_ID
INNER JOIN Member
on Rental.Member_ID = Member.Member_ID
INNER JOIN Tool_Instance
on Rental_Line.Tool_Instance_ID = Tool_Instance.Tool_Instance_ID
INNER JOIN Tool
on Tool_Instance.Tool_ID = Tool.Tool_ID
where Tool.Name = '%&_%';
You could create a stored procedure that takes in a parameter, something like:
CREATE PROCEDURE rentalReport(toolName IN varchar)
AS
--your query here
where Tool.Name = toolName
not sure about the exact syntax, haven't used Oracle db..
More info:
http://www.ics.com/files/docs/dx/tut6.html
You should use ACCEPT command - it enables user to interact with your script. Like this:
09:26:55 SYSTEM#dwal> create table t (key number primary key, value varchar2(10));
Table created.
09:27:15 SYSTEM#dwal> insert into t values (1, 'abcdef');
1 row created.
09:27:20 SYSTEM#dwal> insert into t values (2, 'ghijkl');
1 row created.
09:27:32 SYSTEM#dwal> commit;
Commit complete.
09:28:48 SYSTEM#dwal> accept search_str char prompt "enter parameter > ";
enter parameter > def
09:30:01 SYSTEM#dwal> select * from t where value like '%&search_str.%';
KEY VALUE
---------- ----------
1 abcdef

Resources