How can I transform a statement involving an OR condition to a UNION ALL?
Original Statement:
SELECT dname, loc FROM dept WHERE loc = 'CHICAGO' OR loc = 'NEW YORK'; New Statement:
SELECT dname, loc FROM dept WHERE loc = 'CHICAGO' UNION ALL SELECT dname, loc FROM dept WHERE loc = 'NEW YORK';
How do I eliminate duplicate values in a table?
Provided below are four methods for identifying or removing duplicate rows from a table:
Method 1:
DELETE FROM emp a WHERE rowid > ( SELECT min(rowid) FROM emp b WHERE a.emp_id = b.emp_id ); Method 2:
CREATE TABLE emp2 AS SELECT distinct * FROM emp; DROP TABLE emp; RENAME emp2 TO emp; Method 3:
DELETE FROM emp WHERE rowid NOT IN ( SELECT MIN(rowid) FROM emp GROUP BY emp_id ); Method 4:
DELETE FROM emp a WHERE EXISTS ( SELECT 'true' FROM emp b WHERE b.emp_id = a.emp_id AND b.rowid <> ); NOTE: If you where to create an index on the joined fields in the inner loop, it may be possible to eliminate N^2 operations as there would be no need to loop through the entire table on each pass be a record.
How can I get a count of the different data values in a column?
SELECT
dname , sum(decode(job, 'CLERK', 1, 0)) Clerk , sum(decode(job, 'SALESMAN', 1, 0)) Salesman , sum(decode(job, 'MANAGER', 1, 0)) Manager , sum(decode(job, 'ANALYST', 1, 0)) Analyst , sum(decode(job, 'PRESIDENT', 1, 0)) President FROM emp e , dept d WHERE e.deptno (+) = d.deptno GROUP BY dname;DNAME CLERK SALESMAN MANAGER ANALYST PRESIDENT
-------------- ---------- ---------- ---------- ---------- ----------ACCOUNTING 1 0 1 0 1
OPERATIONS 0 0 0 0 0
RESEARCH 2 0 1 2 0
SALES 1 4 1 0 0
How can I get count/sum RANGES of data values in a column?
A value "x" will be between values "y" and "z" if: GREATEST(x,y)=LEAST(x,z).
SELECT
job , sum(decode(greatest(sal,2999), least(sal,6000), 1, 0)) "Range 3000-6000" , sum(decode(greatest(sal,1000), least(sal,2999), 1, 0)) "Range 1000-3000" , sum(decode(greatest(sal,0), least(sal,999), 1, 0)) "Range 0-1000" FROM emp GROUP BY job;JOB Range 3000-6000 Range 1000-3000 Range 0-1000
--------- --------------- --------------- ------------ANALYST 2 0 0
CLERK 0 2 2
MANAGER 0 3 0
PRESIDENT 1 0 0
SALESMAN 0 4 0
How can I dynamically generate a list of comma-separated items?
I often find myself needing to dynamically generate a list of comma-separated items (i.e. a list of database files separated by commas). The output format, for example, would be:
... Datafile1, Datafile2, Datafile3 ... Instead of thinking of the list as a linear set of items, re-write the set of items each on a separate line as follows:
...
Datafile1 , Datafile2 , Datafile3...
Notice that a comma is used on each line except for the first item. We can now take advantage of a popular Analytic Function (RANK) to distinguish the first line.
Consider the following CREATE CONTROLFILE example:
SET HEADING OFFSET TERMOUT OFFSET FEEDBACK OFFSET VERIFY OFFSET PAGESIZE 9000SET LINESIZE 135SET TRIMSPOOL ONSET TRIMOUT ONSET ECHO OFFSET SQLBLANKLINES ON SPOOL cr_control_file_example.sql prompt CREATE CONTROLFILE SET DATABASE testdb RESETLOGS NOARCHIVELOGprompt MAXLOGFILES 16prompt MAXLOGMEMBERS 3prompt MAXDATAFILES 100prompt MAXINSTANCES 8prompt MAXLOGHISTORY 3182prompt LOGFILEprompt GROUP 1 (prompt '/u03/oradata/testdb/onlinelog/o1_mf_1_34tn7rv7_.log',prompt '/u03/oradata/testdb/onlinelog/o1_mf_1_34tn7sov_.log'prompt ) SIZE 50M,prompt GROUP 2 (prompt '/u03/oradata/testdb/onlinelog/o1_mf_2_34tn7v0s_.log',prompt '/u03/oradata/testdb/onlinelog/o1_mf_2_34tn7v7j_.log'prompt ) SIZE 50M,prompt GROUP 3 (prompt '/u03/oradata/testdb/onlinelog/o1_mf_3_34tn7wj5_.log',prompt '/u03/oradata/testdb/onlinelog/o1_mf_3_34tn7wqp_.log'prompt ) SIZE 50Mprompt DATAFILE SELECT CASE WHEN ROW_NUMBER() OVER(ORDER BY name) = 1 THEN ' ''' || name || '''' ELSE ' , ''' || name || '''' END AS file_nameFROM v$datafile; prompt CHARACTER SET WE8ISO8859P1 SPOOL OFF------------------------------------------------------------
CREATE CONTROLFILE SET DATABASE testdb RESETLOGS NOARCHIVELOG
MAXLOGFILES 16
MAXLOGMEMBERS 3
MAXDATAFILES 100
MAXINSTANCES 8
MAXLOGHISTORY 3182
LOGFILE
GROUP 1 (
'/u03/oradata/testdb/onlinelog/o1_mf_1_34tn7rv7_.log'
, '/u03/oradata/testdb/onlinelog/o1_mf_1_34tn7sov_.log'
) SIZE 50M,
GROUP 2 (
'/u03/oradata/testdb/onlinelog/o1_mf_2_34tn7v0s_.log'
, '/u03/oradata/testdb/onlinelog/o1_mf_2_34tn7v7j_.log'
) SIZE 50M,
GROUP 3 (
'/u03/oradata/testdb/onlinelog/o1_mf_3_34tn7wj5_.log'
, '/u03/oradata/testdb/onlinelog/o1_mf_3_34tn7wqp_.log'
) SIZE 50M
DATAFILE
'+ORCL_DATA1/orcl/datafile/example.263.623550121' , '+ORCL_DATA1/orcl/datafile/soe.269.623559923' , '+ORCL_DATA1/orcl/datafile/soeindex.270.623560217' , '+ORCL_DATA1/orcl/datafile/sysaux.261.623550085' , '+ORCL_DATA1/orcl/datafile/system.259.623549989' , '+ORCL_DATA1/orcl/datafile/undotbs1.260.623550053' , '+ORCL_DATA1/orcl/datafile/undotbs2.264.623550147' , '+ORCL_DATA1/orcl/datafile/users.265.623550181'CHARACTER SET WE8ISO8859P1
Can I retrieve only the Nth row from a table?
Method 1:
SELECT
ename , job , hiredate FROM emp WHERE rowid = ( SELECT rowid FROM emp WHERE rownum <= 3 MINUS SELECT rowid FROM emp WHERE rownum <> ); Method 2:
SELECT
ename , job , hiredate FROM emp WHERE rownum = 1 AND rowid NOT IN ( SELECT rowid FROM emp WHERE rownum <> ); NOTE: Always remember that there is no explicit order in a relational database.
Can I retrieve only rows X to Y from a table?
SELECT
ename , job , hiredate FROM emp WHERE rowid in ( SELECT rowid FROM emp WHERE rownum <= 7 MINUS SELECT rowid FROM emp WHERE rownum <> );
Can I retrieve EVERY Nth row from a table?
Method 1:
SELECT
ename , job , hiredate FROM emp WHERE (rowid,0) in ( SELECT rowid, mod(rownum,4) FROM emp ); Method 2: Using Dynamic Views: (available in Oracle7.2 and higher)
SELECT
ename , job , hiredate FROM ( SELECT rownum rn, empno, ename, job, hiredate FROM emp ) d_table WHERE mod(d_table.rn,4) = 0;
Retrieve the TOP N Rows from a table?
Method 1: Starting with Oracle8i, you can have an inner-query with an ORDER BY clause
SELECT
ename , job , hiredate , sal FROM ( SELECT empno, ename, job, hiredate, sal FROM emp ORDER BY sal DESC ) WHERE rownum <> Method 2: The following workaround will work with prior releases
SELECT
ename , job , hiredate , sal FROM emp a WHERE 5 >= ( SELECT count(distinct b.sal) FROM emp b WHERE b.sal >= a.sal ) ORDER BY a.sal DESC
No comments:
Post a Comment