I'm using this script:
COLUMN c1 HEADING 'Col1'
COLUMN c2 HEADING 'Col2'
COLUMN c3 HEADING 'Col3'
select c1, c2, c3 from t1 ORDER BY c1
this is what it shows:
Col1 Col2
-------------------- --------------------
Col3
----------------------------------------
aaa bbb
qqq
ccc ddd
rrr
eee fff
ppp
Col1 Col2
-------------------- --------------------
Col3
----------------------------------------
ggg hhh
iii
jjj kkk
lll
mmm nnn
ooo
As shown I don't know why the third column is displayed in a newline and why the header is repeatedly displayed every 3 rows?
This reminds me of a similar "issue" in sqlplus.
Have you tried?
set linesize 200;
edit (additionally):
I believe this removes a lot of the spacing between the columns:
set sqlformat ansiconsole;
And this will put all rows after another:
set pagesize 30;
If its still messy, try increasing the numbers
I agree that your current output is ugly. One workaround would be to just UNION the header on explicitly:
SELECT t.c1, t.c2, t.c3
FROM
(
SELECT 'Col1' AS c1, 'Col2' AS c2, 'Col3' AS c3, 1 AS pos
FROM dual
UNION
SELECT c1, c2, c3, 2 AS pos
FROM t1
) t
ORDER BY t.pos,
t.c1
This should work assuming that the c1, c2, and c3 columns are varchar, which is compatible with the text appearing in the header record.
Related
CREATE TABLE TABLE1
(
C1 VARCHAR2(3), C2 VARCHAR2(3), C3 VARCHAR2(4)
);
INSERT INTO TABLE1 VALUES('A', '0', '1234');
INSERT INTO TABLE1 VALUES('A', '1', '4568');
INSERT INTO TABLE1 VALUES('A', '2', '5432');
INSERT INTO TABLE1 VALUES('B', '0', '3562');
INSERT INTO TABLE1 VALUES('B', '1', Null);
INSERT INTO TABLE1 VALUES('B', '2', Null);
INSERT INTO TABLE1 VALUES('C', '0', '2132');
INSERT INTO TABLE1 VALUES('C', '1', Null);
INSERT INTO TABLE1 VALUES('C', '2', '5431');
When you execute above query, we get the data into TABLE1 and each unique value of C1 column corresponds to 3 lines i.e. 0,1,2 (in C2 column). What is the query to select the data of column1 having its first line i.e. 0 in column2 has a value(which is not null) in C3 and all other lines of C2 have a value as Null in C3.
The answer for above example is
C1 C2 C3
------------------
B 0 3562
B 1 Null
B 2 Null
There are various rows. For each unique value of C1 can have multiple lines i.e. 0 to 100 etc. in C2 but I have taken above one as an example. In above you can see that A has values in all the 3 lines. B has value in 0th line but as Null in all other lines. C has values in 0th line and 2nd line but Null in 1st line. We need to select the unique value of C1 having value in 0th line and Null in other lines
Perhaps something like this:
select *
from table1
where c1 in (
select c1
from table1
group by c1
having count(case when c2 = 0 then c3 end) = 1
and count(c3) = 1
)
order by c1, c2
;
C1 C2 C3
--- --- ----
B 0 3562
B 1
B 2
This reads the base data twice. If you use analytic functions instead, you can have the base data read just once, but analytic functions themselves are slower than traditional aggregation. If this query works for you, but it is slow, you can try the analytic functions approach just to make sure, but I expect it will be slower, not faster.
Is column c2 supposed to be numeric? I treated it as such, but in your sample data you gave it as strings.
I am using oracle SQLcl: Release 4.2.0.
When I issue this sort of select statement:
column COLUMN_A format a8
column COLUMN_B format a8
column COLUMN_C format a8
column COLUMN_D format a8
set linesize 1300
select * from table1 where rownum <= 10 order by 1;
I have the following issue:
COLUMN_A COLUMN_B COLUMN_C COLUMN_D
-------- -------- -------- --------
data1 text1 string1 date1
data2 text2 string2 date2
data3 text3 string3 date3
The data in the table output doesn't abide by the columns shown in the heading. Is there a setting that I can use so that the data in the columns fit properly in the table's columns?
I ssh into the machine that is running Oracle, via the Terminal app on a MacBook.
Maybe upgrade?
Latest version (18.3)
drop table a8_format;
clear screen
create table a8_format (co11 varchar2(20), col2 varchar2(20), col3 varchar2(20), col4 varchar2(20));
insert into a8_format values ('data1', 'text1', 'string1', 'date1');
insert into a8_format values ('data2', 'text2', 'string2', 'date2');
insert into a8_format values ('data3', 'text3', 'string3', 'date3');
insert into a8_format values ('data4', 'text4', 'string4', 'date4');
col CO11 format a8
col col2 format a8
col col3 format a8
col col4 format a8
select * from a8_format;
Execute via F5
Also make sure you're using a fixed width font for the Code Editor
1.Increase the column width in format command
Or
2. Use LPAD with expr2 as 12 (Or more depending upon the format spaces)
I have two tables A and B.
Table A has structure like below:
col1 | col2 | col3 | col4 | col5 | ....
Table B has only one entry with many columns, for example ( just taking 5) :
c1 c2 c3 c4 c5 ...
-- -- -- -- --
1 0 1 1 0 ...
Now I want to generate query dynamically in a stored procedure based the value of table B row. Only select columns which has corresponding value 1.
Example 1: For above entry query will look like :
select col1,
col3,
col4
from A;
Example 2 : If entry in B is like below
c1 c2 c3 c4 c5 ...
-- -- -- -- --
0 0 1 1 0 ...
For above entry query will look like :
select col3,
col4
from A;
It's not a good table design to store columns as lookup values. You may achieve it using UNPIVOT, but the mapping has to be explicitly listed.
SELECT
'SELECT ' ||LISTAGG(
CASE
WHEN col = 1 THEN val
END,',') WITHIN GROUP(
ORDER BY col
) ||' FROM A' as query
FROM b UNPIVOT ( col
FOR val
IN ( c1 as 'COL1',
c2 as 'COL2',
c3 as 'COL3',
c4 as 'COL4',
c5 as 'COL5') );
demo
I have a table EMPLOYEE with the following fields:
ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH
01-20-2001 123 ABC D1 N
01-20-2012 123 ABC D2 N
10-12-2016 123 RST D2 N
02-10-2017 123 RST D3 N
02-10-2017 456 TYU D2 N
I have another table EMPLOYE_CUR
ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH
02-23-2017 123 PQR D4 N
02-23-2017 456 TYU D2 Y
I need to insert records into table EMPLOYEE only if its a new record (New being record is changed for EMP_ID or EMP_NAME or DEPT, even if SWITCH is changed we wont insert that record)
We will be comparing the reocrd for the emp_ID for hisgest ENROLL_DATE. So if the record is changed based on the latest record for the emp_ID in table EMPLOYEE then only we will be inserting that record.
So in above case the records which need to be inserted are:
ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH
02-23-2017 123 PQR D4 N
So employee table will now have:
ENROLL_DATE EMP ID EMP_NAME DEPT SWITCH
01-20-2001 123 ABC D1 N
01-20-2012 123 ABC D2 N
10-12-2016 123 RST D2 N
02-10-2017 123 RST D3 N
02-19-2017 123 RST D4 Y
02-23-2017 123 PQR D4 N
I was trying to do this using cursor getting all the records form EMPLOYEE table with highest Enroll_date and then thinking to compare that with EMPLOYEE_CUR table, but could not figure out how to do.
Can anyone help me with the query here?
Thanks!
Here you find a simplified solution, that should give you advice how to handle your possible special cases.
Note that I assume that the common history is identical in both tables and that a
new employee will be created in both tables.
If this is not true you mast refine the query to address it.
The solution has two parts:
1) filter idle records in EMPLOYE_CUR that corresponds to no change (e.g. only SWITCH changed) - use analytical functions to trace the last values
2) select the real change records that have ENROLL_DATE higher that the MAX(ENROLL_DATE) from table EMPLOYEE
(The last step INSERT is not considered as obvious.) - see below
STEP 1
with history as (
select ENROLL_DATE, EMP_ID, EMP_NAME, DEPT,SWITCH,
LAG(EMP_NAME) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_EMP_NAME,
LAG(DEPT) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_DEPT
from EMPLOYE_CUR)
select
ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH,
case when EMP_NAME != PREV_EMP_NAME or DEPT != PREV_DEPT then 'Y' end is_changed
from history;
ENROLL_DATE EMP_ID EMP_NAME DEPT SWITCH IS_CHANGED
------------------- ---------- ---------- ---------- ---------- ----------
20.01.2001 00:00:00 123 ABC D1 N
20.01.2012 00:00:00 123 ABC D2 N Y
12.10.2016 00:00:00 123 RST D2 N Y
10.02.2017 00:00:00 123 RST D3 N Y
17.02.2017 00:00:00 123 RST D3 Y
19.02.2017 00:00:00 123 RST D4 Y Y
23.02.2017 00:00:00 123 PQR D4 N Y
STEP 2
with history as (
select ENROLL_DATE, EMP_ID, EMP_NAME, DEPT,SWITCH,
LAG(EMP_NAME) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_EMP_NAME,
LAG(DEPT) OVER (PARTITION BY EMP_ID ORDER BY ENROLL_DATE) PREV_DEPT
from EMPLOYE_CUR),
clean_history as (
select
ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH,
case when EMP_NAME != PREV_EMP_NAME or DEPT != PREV_DEPT then 'Y' end is_changed
from history)
select clean_history.ENROLL_DATE, clean_history.EMP_ID, EMP_NAME, DEPT, SWITCH from clean_history
join (select EMP_ID, max(ENROLL_DATE) ENROLL_DATE from EMPLOYEE group by EMP_ID) e
on clean_history.EMP_ID = e.EMP_ID and clean_history.ENROLL_DATE > e.ENROLL_DATE
where is_changed = 'Y';
ENROLL_DATE EMP_ID EMP_NAME DEPT SWITCH
------------------- ---------- ---------- ---------- ----------
19.02.2017 00:00:00 123 RST D4 Y
23.02.2017 00:00:00 123 PQR D4 N
I used the below query and its working fine. Not sure if i covered all scenarios:
INSERT into EMPLOYEE(ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH)
SELECT ENROLL_DATE, EMP_ID, EMP_NAME, DEPT, SWITCH FROM EMPLOYEE_CUR
WHERE NOT EXISTS (SELECT * FROM EMPLOYEE A WHERE A.EMP_ID = EMPLOYEE_CUR.EMP_ID
AND A.EMP_NAME = EMPLOYEE_CUR.EMP_NAME
AND DEPT= EMPLOYEE_CUR.DEPT
AND A.Enroll_date in (SELECT MAX(enroll_date) over ( partition by emp_id) as max_date from employee b where a.emp_id=b.emp_id));
Can someone comment if it looks correct?
I need to create a bat file which include a query to run a package.
I use plsql developer to develop the package. its username,password and database is user,pswd,db1 respectively.
The query to run the package is:
SELECT
COLUMN1 AS "LAST NAME",
COLUMN2 AS "FIRST NAME",
COLUMN3 AS "LOCATION"
FROM TABLE(PKG.GET_SUM('09-NOV-2010','12-NOV-2010'))
can anyone help me what code shud I write to create a bat file
Thanks in advance
This is my code
connect usr/pswd#db1
SET NEWPAGE 0
SET SPACE 0
SET LINESIZE 80
SET PAGESIZE 100
COLUMN COLUMN1 HEADING 'LAST NAME'
COLUMN COLUMN2 HEADING 'FIRST NAME'
COLUMN COLUMN3 HEADING 'LOCATION'
spool c:\temp\get_sums.csv
SELECT COLUMN1
,COLUMN2
,COLUMN3
,COLUMN4
,COLUMN5
, COLUMN6
,COLUMN7,
COLUMN8
,COLUMN9
FROM TABLE(ACTY_SUMM('09-NOV-2010','12-NOV-2010'))
/
spool off
exit;
I changed the line size and pagesize. But not able to get the desirable format. I have 12 columns. I need it in a report format.
Hi I tried to change the Linesize,but still I am not getting the desired format. I want the report in the following format
FirstNAME LASTNAME LOCATION A B C D E F G H I
NAME1 LNAME1 LOC1 A1 B1 C1 D1 E1 F1 G1 H1 I1
NAME2 LNAME2 LOC1 A2 B2 C2 D2 E2 F2 G2 H2 I2
LOCTOT
NAME3 LNAME3 LOC2 A3 B3 C3 D3 E3 F3 G3 H3 I3
LOCTOT
I need all the column in one row and their corresponding values of each person under each column and after each location there will be location total and at the end there will be grant total. I tried with the linesize,page size and all. still no result. Can anyone help me to get the report in this format
Hi
As of now client is ok with the csv format. But the challenge is I am not getting the heading. This is my code in sql script.
connect usr/pwd#db1
SET NEWPAGE 0
SET LINESIZE 100
SET PAGESIZE 0
spool c:\temp\q1.csv
COLUMN COLUMN1 HEADING 'LAST NAME'
COLUMN COLUMN2 HEADING 'FIRST NAME'
COLUMN COLUMN3 HEADING 'LOCATION'
COLUMN COLUMN4 HEADING 'A'
COLUMN COLUMN5 HEADING 'B'
COLUMN COLUMN6 HEADING 'C'
COLUMN COLUMN7 HEADING 'D'
COLUMN COLUMN8 HEADING 'E'
COLUMN COLUMN9 HEADING 'F'
COLUMN COLUMN10 HEADING 'G'
COLUMN COLUMN11 HEADING 'H'
COLUMN COLUMN12 HEADING 'I'
SELECT
'"'||COLUMN1
||'","'|| COLUMN2
||'","'|| COLUMN3
||'","'|| COLUMN4
||'","'|| COLUMN5
||'","'|| COLUMN6
||'","'|| COLUMN7
||'","'|| COLUMN8
||'","'|| COLUMN9
||'","'|| COLUMN10
||'","'|| COLUMN11
||'","'|| COLUMN12||'"'
FROM
TABLE(ACTY_SUM('09-NOV-2010','12-NOV-2010'))
/
spool off
exit;
Can you please suggest on this issue
First create a script to run the query. You'll want to capture the output to a file, hence the SPOOL command.
connect usr/pswd#db1
spool c:\temp`get_sums.lst
SELECT
COLUMN1 AS "LAST NAME",
COLUMN2 AS "FIRST NAME",
COLUMN3 AS "LOCATION"
FROM TABLE(PKG.GET_SUM('09-NOV-2010','12-NOV-2010'))
/
spool off
exit;
save that to a file called get_sums.sql . Then you need a batch file get_sums.bat like this:
sqlplus /nolog #C:\get_sums.sql
There are various SQL*Plus commands you can include in the .sql file t format the output. Find out more.
Apparently a link to the formatting documentation is not sufficient.
There is no point in setting LINESiZE to 80, that is the default. If you are selecting nine columns and you want all nine values to appear on one line you need to set the LINESIZE so that it is long enough to accomodate all the columns. This means you need to set LINESIZE to the sum of all the columns' widths plus eight (the number of interstitial spaces between ninbe columns).
Although I see you have tried
SET SPACE 0
This causes all the selected columns to run together in one long line, which is a highly unusual way of laying out a report. But if that's really what you want then ignore the interstitial spaces when calculating the correct value for LINESIZE.
Having formatted you posted code I see you are outputting to .csv. Why didn't you say you wanted to export comma separated values in the first place?
There are several ways of doing this. The most straightforward is to concatenate your query's projection with commas:
SELECT
'"'||COLUMN1
||'","'|| COLUMN2
||'","'|| COLUMN3
||'","'|| COLUMN4
||'","'|| COLUMN5
||'","'|| COLUMN6
||'","'|| COLUMN7
||'","'|| COLUMN8
||'","'|| COLUMN9 ||'"'
FROM TABLE(ACTY_SUMM('09-NOV-2010','12-NOV-2010'))
/
The double-quotes are the optional field terminators, which will handle any string columns which contain commas.
"I dont want coma seperated values. I
edited my post. Please suggest "
Here is some test data:
SQL> select * from t23
2 /
♀FIRSTNAME LASTNAME LOCATION A B C D E F
-------------------- -------------------- ---------- -- -- -- -- -- --
G H I
-- -- --
NAME1 LNAME1 LOC1 A1 B1 C1 D1 E1 F1
G1 H1 I1
NAME2 LNAME2 LOC1 A2 B2 C2 D2 E2 F2
G2 H2 I2
NAME3 LNAME3 LOC2 A3 B3 C3 D3 E3 F3
G3 H3 I3
SQL>
I can produce the basic layout you want using SQL*Plus formatting commands
SQL> set linesize 100
SQL> break on location
SQL> compute count of location on location
SQL> compute count of location on report
SQL> r
1* select * from t23
♀FIRSTNAME LASTNAME LOCATION A B C D E F G H I
-------------------- -------------------- ---------- -- -- -- -- -- -- -- -- --
NAME1 LNAME1 LOC1 A1 B1 C1 D1 E1 F1 G1 H1 I1
NAME2 LNAME2 A2 B2 C2 D2 E2 F2 G2 H2 I2
----------
2
NAME3 LNAME3 LOC2 A3 B3 C3 D3 E3 F3 G3 H3 I3
----------
1
SQL>