標籤

4GL (1) 人才發展 (10) 人物 (3) 太陽能 (4) 心理 (3) 心靈 (10) 文學 (31) 生活常識 (14) 光學 (1) 名句 (10) 即時通訊軟體 (2) 奇狐 (2) 爬蟲 (1) 音樂 (2) 產業 (5) 郭語錄 (3) 無聊 (3) 統計 (4) 新聞 (1) 經濟學 (1) 經營管理 (42) 解析度 (1) 遊戲 (5) 電學 (1) 網管 (10) 廣告 (1) 數學 (1) 機率 (1) 雜趣 (1) 證券 (4) 證券期貨 (1) ABAP (15) AD (1) agentflow (4) AJAX (1) Android (1) AnyChart (1) Apache (14) BASIS (4) BDL (1) C# (1) Church (1) CIE (1) CO (38) Converter (1) cron (1) CSS (23) DMS (1) DVD (1) Eclipse (1) English (1) excel (5) Exchange (4) Failover (1) Fedora (1) FI (57) File Transfer (1) Firefox (3) FM (2) fourjs (1) Genero (1) gladiatus (1) google (1) Google Maps API (2) grep (1) Grub (1) HR (2) html (23) HTS (8) IE (1) IE 8 (1) IIS (1) IMAP (3) Internet Explorer (1) java (4) JavaScript (22) jQuery (6) JSON (1) K3b (1) ldd (1) LED (3) Linux (120) Linux Mint (4) Load Balance (1) Microsoft (2) MIS (2) MM (51) MSSQL (1) MySQL (27) Network (1) NFS (1) Office (1) OpenSSL (1) Oracle (130) Outlook (3) PDF (6) Perl (60) PHP (33) PL/SQL (1) PL/SQL Developer (1) PM (3) Postfix (2) postfwd (1) PostgreSQL (1) PP (50) python (5) QM (1) Red Hat (4) Reporting Service (28) ruby (11) SAP (234) scp (1) SD (16) sed (1) Selenium (3) Selenium-WebDriver (5) shell (5) SQL (4) SQL server (8) sqlplus (1) SQuirreL SQL Client (1) SSH (3) SWOT (3) Symantec (2) T-SQL (7) Tera Term (2) tip (1) tiptop (24) Tomcat (6) Trouble Shooting (1) Tuning (5) Ubuntu (37) ufw (1) utf-8 (1) VIM (11) Virtual Machine (2) VirtualBox (1) vnc (3) Web Service (2) wget (1) Windows (19) Windows (1) WM (6) Xvfb (2) youtube (1) yum (2)
顯示具有 SQL 標籤的文章。 顯示所有文章
顯示具有 SQL 標籤的文章。 顯示所有文章

2013年7月14日 星期日

Oracle 12c TOP-N SQL

http://www.oracle-base.com/articles/12c/row-limiting-clause-for-top-n-queries-12cr1.php

Introduction

A Top-N query is used to retrieve the top or bottom N rows from an ordered set. Combining two Top-N queries gives you the ability to page through an ordered set. This concept is not a new one. In fact, Oracle already provides multiple ways to perform Top-N queries, as discussed here. These methods work fine, but they look rather complicated compared to the methods provided by other database engines. For example, MySQL uses a LIMIT clause to page through an ordered result set.
SELECT * 
FROM   my_table 
ORDER BY column_1
LIMIT 0 , 40
Oracle 12c has introduced the row limiting clause to simplify Top-N queries and paging through ordered result sets.

Setup

To be consistent, we will use the same example table used in the Top-N Queries article.
Create and populate a test table.
DROP TABLE rownum_order_test;

CREATE TABLE rownum_order_test (
  val  NUMBER
);

INSERT ALL
  INTO rownum_order_test
  INTO rownum_order_test
SELECT level
FROM   dual
CONNECT BY level <= 10;

COMMIT;
The following query shows we have 20 rows with 10 distinct values.
SELECT val
FROM   rownum_order_test
ORDER BY val;

       VAL
----------
         1
         1
         2
         2
         3
         3
         4
         4
         5
         5
         6

       VAL
----------
         6
         7
         7
         8
         8
         9
         9
        10
        10

20 rows selected.

SQL>

Top-N Queries

The syntax for the row limiting clause looks a little complicated at first glance.
[ OFFSET offset { ROW | ROWS } ]
[ FETCH { FIRST | NEXT } [ { rowcount | percent PERCENT } ]
    { ROW | ROWS } { ONLY | WITH TIES } ]
Actually, for the classic Top-N query it is very simple. The example below returns the 5 largest values from an ordered set. Using the ONLY clause limits the number of rows returned to the exact number requested.
SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS ONLY;

       VAL
----------
        10
        10
         9
         9
         8

5 rows selected.

SQL>
Using the WITH TIES clause may result in more rows being returned if multiple rows match the value of the Nth row. In this case the 5th row has the value "8", but there are two rows that tie for 5th place, so both are returned.
SELECT val
FROM   rownum_order_test
ORDER BY val DESC
FETCH FIRST 5 ROWS WITH TIES;

       VAL
----------
        10
        10
         9
         9
         8
         8

6 rows selected.

SQL>
In addition to limiting by row count, the row limiting clause also allows us to limit by percentage of rows. The following query returns the bottom 20% of rows.
SELECT val
FROM   rownum_order_test
ORDER BY val
FETCH FIRST 20 PERCENT ROWS ONLY;

       VAL
----------
         1
         1
         2
         2

4 rows selected.

SQL>

Paging Through Data

Paging through an ordered resultset was a little annoying using the classic Top-N query approach, as it required two Top-N queries, one nested inside the other. For example, if we wanted the second block of 4 rows we might do the following.
SELECT val
FROM   (SELECT val, rownum AS rnum
        FROM   (SELECT val
                FROM   rownum_order_test
                ORDER BY val)
        WHERE rownum <= 8)
WHERE  rnum >= 5;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

SQL>
With the row limiting clause we can achieve the same result using the following query.
SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 4 ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

SQL>
The starting point for the FETCH is OFFSET+1.
The OFFSET is always based on a number of rows, but this can be combined with a FETCH using a PERCENT.
SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET 4 ROWS FETCH NEXT 20 PERCENT ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

4 rows selected.

SQL>
Not surprisingly, the offset, rowcount and percent can, and probably should, be bind variables.
VARIABLE v_offset NUMBER;
VARIABLE v_next NUMBER;

BEGIN
  :v_offset := 4;
  :v_next   := 4;
END;
/

SELECT val
FROM   rownum_order_test
ORDER BY val
OFFSET :v_offset ROWS FETCH NEXT :v_next ROWS ONLY;

       VAL
----------
         3
         3
         4
         4

SQL>

Extra Information

  • The keywords ROW and ROWS can be used interchangeably, as can the FIRST and NEXT keywords. Pick the ones that scan best when reading the SQL like a sentence.
  • If the offset is not specified it is assumed to be 0.
  • Negative values for the offset, rowcount or percent are treated as 0.
  • Null values for offset, rowcount or percent result in no rows being returned.
  • Fractional portions of offset, rowcount or percent are truncated.
  • If the offset is greater than or equal to the total number of rows in the set, no rows are returned.
  • If the rowcount or percent are greater than the total number of rows after the offset, all rows are returned.
  • The row limiting clause can not be used with the FOR UPDATE clause, CURRVAL and NEXTVAL sequence pseudocolumns or in an fast refresh materialized view.
For more information see:

2012年2月23日 星期四

殖利率_ROA_ROE

select stkid,stknm,excorp,roa,roe,殖利率,dcash 平均現金股利,
       --sum(殖利率_rank+roa_rank) ranks,
       --sum(殖利率_rank+roe_rank) ranks,
       sum(殖利率_rank+roa_rank+roe_rank) ranks,
       closep,volume,industry
  from (
select /*+ index(b) index(c)*/
       a.stkid,b.stknm,b.industry,b.excorp,
       rank() over(order by avg(dcash)/c.closep desc) 殖利率_rank,
       roa_rank,roe_rank,roa,roe,
       round(avg(dcash),3) dcash,
       round(stddev(dcash),3) stdev,
       round(stddev(dcash)/avg(dcash),3) variation,
       round(avg(dcash)/c.closep*100,2) 殖利率,
       b.bps,c.closep,c.volume      
  from (
        select stkid,yyyy,dcash
          from stk_dividends a
         where yyyy between '2007' and '2010'
           and exists (
                       select /*+ index(b)*/null
                         from stk_dividends b
                        where a.stkid = b.stkid
                       having count(b.yyyy) >= 4
                      )
         union all
        select stkid,substr(yyyyq,1,4) yyyy,greatest(sum(eps)*70/75,0) eps --保守原則
          from stk_eps
         where yyyyq between '20111' and '20113'
         group by stkid,substr(yyyyq,1,4)
       ) a,stk_names b,stk_trans c,
       (
        select a.stkid,round(avg(roa),2) roa, round(avg(roe),2) roe,
               rank() over(order by avg(roa) desc) roa_rank,
               rank() over(order by avg(roe) desc) roe_rank
          from (
                select stkid,roa,roe
                  from stk_eps
                 where yyyy between '2007' and '2010'
                 union all
                select stkid,sum(roa)*1.06 roa,sum(roe)*1.06 roe --用前三季保守推算全年
                  from stk_eps
                 where yyyyq between '20111' and '20113'
                 group by stkid
               ) a,stk_names b
         where a.stkid = b.stkid
           and b.excorp = '上市'
         group by a.stkid
       ) d
 where a.stkid = b.stkid
   and a.stkid = c.stkid
   and c.stkdt = '20120223'
   and a.stkid = d.stkid
   and c.closep > 0
 group by a.stkid,b.stknm,c.closep,c.volume,b.industry,b.excorp,b.bps,roa_rank,roe_rank,roa,roe
having avg(dcash) > 0 and stddev(dcash) > 0 and avg(dcash)/c.closep >= 0.0625 and stddev(dcash)/avg(dcash) <= 0.4
       )
 group by stkid,stknm,roa,roe,殖利率,closep,volume,industry,dcash,excorp
 order by ranks

2012年2月15日 星期三

SQL : 融資融券 vs. 三大法人

select stkdt,stkid,stknm,margin,short,to_char(券資比,'990.99')||' %' 券資比
  from (
        select a.stkdt,a.stkid,b.stknm,a.margin,a.short,
               round(a.short/nullif(a.margin,0)*100,2) 券資比,
               lag(a.short/nullif(a.margin,0),1) over(partition by a.stkid order by a.stkdt) 券資比_1,
               lag(a.short/nullif(a.margin,0),2) over(partition by a.stkid order by a.stkdt) 券資比_2,
               lag(a.short/nullif(a.margin,0),3) over(partition by a.stkid order by a.stkdt) 券資比_3
          from stk_margin a,stk_names b
         where a.stkid = b.stkid
       )
 where 券資比   > 券資比_1
   and 券資比_1 > 券資比_2
   and 券資比_2 > 券資比_3
   and stkdt = '20120215'
 order by stkid,stkdt;

select a.stkdt,a.stkid,a.stknm,a.margin,a.short,to_char(a.券資比,'990.99')||' %' 券資比,
       b.三大法人
  from (
        select a.stkdt,a.stkid,b.stknm,a.margin,a.short,
               round(a.short/nullif(a.margin,0)*100,2) 券資比,
               lag(a.short/nullif(a.margin,0),1) over(partition by a.stkid order by a.stkdt) 券資比_1,
               lag(a.short/nullif(a.margin,0),2) over(partition by a.stkid order by a.stkdt) 券資比_2,
               lag(a.short/nullif(a.margin,0),3) over(partition by a.stkid order by a.stkdt) 券資比_3
          from stk_margin a,stk_names b
         where a.stkid = b.stkid
       ) a,
       (
        select stkid,stknm,sum(nvl(外資,0)+nvl(投信,0)+nvl(自營商,0)) 三大法人
          from (
                select insti,stkdt,stkid,stknm,round(sum(diff)/1000) diff
                  from stk_institutions
                 where stkdt >= '20120213'
                 group by insti,stkdt,stkid,stknm
               )
         pivot (
                sum(diff) for insti in ('F' 外資,'S' 投信,'D' 自營商)
               )
         group by stkid,stknm
        having sum(nvl(外資,0)+nvl(投信,0)+nvl(自營商,0)) > 0
       ) b
 where 券資比   > 券資比_1
   and 券資比_1 > 券資比_2
   and 券資比_2 > 券資比_3
   and stkdt = '20120215'
   and a.stkid = b.stkid
 order by a.stkid,a.stkdt;

SQL : 營收成長

select a.stkid,b.stknm,b.industry,a.rmnth,a.last_year,a.this_year,
       case
       when rmnth = to_char(add_months(sysdate,-1),'mm') then
         round((sum(a.this_year) over(partition by a.stkid order by a.rmnth) - sum(a.last_year) over(partition by a.stkid order by a.rmnth) ) /
               sum(a.last_year) over(partition by a.stkid order by a.rmnth)
               * 100 ,2
              )
       else null
        end "營收累積成長%"
  from (
        select *
          from (
                select stkid,substr(rmnth,1,4) ryear,substr(rmnth,5,2) rmnth,
                       earning
                  from stk_earnings
               ) a
         pivot (
                sum(earning) for ryear in ('2011' as last_year,'2012' as this_year)
               )
       ) a,stk_names b
 where a.stkid = b.stkid
 order by a.stkid,a.rmnth;

select industry,excorp,count(*)
  from (
select a.stkid,b.stknm,b.industry,b.excorp,a.rmnth,a.last_year,a.this_year,
       case
       when rmnth = to_char(add_months(sysdate,-1),'mm') then
         round((sum(a.this_year) over(partition by a.stkid order by a.rmnth) - sum(a.last_year) over(partition by a.stkid order by a.rmnth) ) /
               sum(a.last_year) over(partition by a.stkid order by a.rmnth)
               * 100 ,2
              )
       else null
        end "營收累積成長%"
  from (
        select *
          from (
                select stkid,substr(rmnth,1,4) ryear,substr(rmnth,5,2) rmnth,
                       earning
                  from stk_earnings
               ) a
         pivot (
                sum(earning) for ryear in ('2011' as last_year,'2012' as this_year)
               )
       ) a,stk_names b
 where a.stkid = b.stkid
       )
 where "營收累積成長%" > 0
 group by industry,excorp
 order by count(*) desc;

select a.stkid,b.stknm,b.industry,a.rmnth,a.last_year,a.this_year,
       case
       when rmnth = to_char(add_months(sysdate,-1),'mm') then
         round((sum(a.this_year) over(partition by a.stkid order by a.rmnth) - sum(a.last_year) over(partition by a.stkid order by a.rmnth) ) /
               sum(a.last_year) over(partition by a.stkid order by a.rmnth)
               * 100 ,2
              )
       else null
        end "營收累積成長%"
  from (
        select *
          from (
                select stkid,substr(rmnth,1,4) ryear,substr(rmnth,5,2) rmnth,
                       earning
                  from stk_earnings
               ) a
         pivot (
                sum(earning) for ryear in ('2011' as last_year,'2012' as this_year)
               )
       ) a,stk_names b
 where a.stkid = b.stkid
   and b.industry = '金融保險'
   and b.excorp = '上市'
 order by a.stkid,a.rmnth;