Subquery

코드에서 사용되는 데이터 파일 내용은 페이지 아래쪽에 있습니다.

Subquery 는 if ( idx in array ) 를 이용하여 구현할 수 있습니다.

#####################  SQL 문  #######################

SELECT ord_num, ord_amount, ord_date, cust_code, agent_code
FROM orders
WHERE agent_code IN (
    SELECT agent_code FROM agents
    WHERE working_area='Bangalore');

   ORD_NUM ORD_AMOUNT ORD_DATE  CUST_CODE  AGENT_CODE
---------- ---------- --------- ---------- ----------
    200130       2500 30-JUL-08 C00025     A011
    200105       2500 18-JUL-08 C00025     A011
    200117        800 20-OCT-08 C00014     A001
    200124        500 20-JUN-08 C00017     A007
    200112       2000 30-MAY-08 C00016     A007

######################  AWK  ##########################

# $3 : agents.working_area
# $1 : agents.agent_code
# $6 : orders.agent_code
$ awk '
    NR == FNR { if ($3 == "Bangalore") ac[$1]; next } 
    { 
        if ( $6 in ac ) 
            printf "%d %6d %11s %8s %6s\n", $1,$2,$4,$5,$6 
    }
' FS=' *, *' agents FS=' ' orders

200130   2500   30-JUL-08   C00025   A011
200105   2500   18-JUL-08   C00025   A011
200117    800   20-OCT-08   C00014   A001
200124    500   20-JUN-08   C00017   A007
200112   2000   30-MAY-08   C00016   A007

Multiple Column Subquery

SELECT ord_num, agent_code, ord_date, ord_amount
FROM orders
WHERE (agent_code, ord_amount) IN
    (SELECT agent_code, MIN(ord_amount)
     FROM orders 
     GROUP BY agent_code)
ORDER BY agent_code    

 ORD_NUM AGENT_CODE ORD_DATE  ORD_AMOUNT
-------- ---------- --------- ----------
  200117   A001     20-OCT-08        800
  200120   A002     20-JUL-08        500
  200126   A002     24-JUN-08        500
  200123   A002     16-SEP-08        500
  .....
  .....

######################  AWK  ##########################

# $6 : orders.agent_code
# $2 : orders.ord_amount
$ awk -f - <<\EOF orders orders
NR == FNR { 
    if (ac[$6]) { 
        ac[$6] = ( $2 < ac[$6] ? $2 : ac[$6] )   # MIN(ord_amount) 을 위한 부분
    } else { ac[$6] = $2 }
    next 
}{
    if (($6 in ac) && (ac[$6] == $2))
       # 출력때 $6 가 group by 되는 것을 방지하기 위해 i++ 를 추가
       r[$6,i++] = sprintf("%d %6s %11s %6d", $1, $6, $4, $2)
} 
END {
    delete ac
    PROCINFO["sorted_in"] = "@ind_str_asc"
    for ( i in r ) print r[i]
}
EOF

200117   A001   20-OCT-08    800
200120   A002   20-JUL-08    500
200126   A002   24-JUN-08    500
200123   A002   16-SEP-08    500
200100   A003   08-JAN-08   1000
200121   A004   23-SEP-08   1500
200104   A004   13-MAR-08   1500
200103   A005   15-MAY-08   1500
200118   A006   20-JUL-08    500
200124   A007   20-JUN-08    500
200111   A008   10-JUL-08   1000
200116   A009   13-JUL-08    500
200135   A010   16-SEP-08   2000
200130   A011   30-JUL-08   2500
200105   A011   18-JUL-08   2500
200131   A012   26-AUG-08    900

AVERAGE

평균값을 구하기 위해 ac[$6]["AS"] 에는 sum 값이 설정되고 ac[$6]["AC"] 에는 count 값이 설정됩니다. ORDER BY DESC 절을 구현하기 위해 compare() 함수에서 등호로 < 대신 > 가 사용되었습니다.

SELECT agent_code, AVG(ord_amount) AS average
FROM orders
GROUP BY agent_code
ORDER BY average DESC

######################  AWK  ##########################

# $6 : orders.agent_code
# $2 : orders.ord_amount
$ awk -f - <<\EOF orders 
{ 
    ac[$6]["AS"] += $2
    ac[$6]["AC"]++
}
END {
    PROCINFO["sorted_in"] = "compare"
    for ( i in ac ) printf "%s %10d\n", i, ac[i]["AS"] / ac[i]["AC"]
}
function compare(i1, v1, i2, v2,    a1, a2)
{ 
    a1 = v1["AS"] / v1["AC"]
    a2 = v2["AS"] / v2["AC"]
    if ( a1 > a2 )       return -1   # ORDER BY DESC 를 위해 '>' 사용
    else if ( a1 == a2 ) return 0
    else                 return 1
}
EOF

A010       3400
A005       2566
A011       2500
A008       2500
A004       2375
A002       1814
A003       1750
A006       1500
A012       1450
A007       1250
A001        800
A009        500

Data Files

awk 에서 사용할 때는 헤더 부분을 제외하고 사용하시면 됩니다.

$ cat agents
  AGENT_CODE   AGENT_NAME      WORKING_AREA      COMMISSION     PHONE_NO
+------------+--------------+-----------------+------------+-----------------+
A007     ,     Ramasundar   ,   Bangalore     ,       0.15  ,  077-25814763
A003     ,     Alex         ,   London        ,       0.13  ,  075-12458969
A008     ,     Alford       ,   New York      ,       0.12  ,  044-25874365
A011     ,     Ravi Kumar   ,   Bangalore     ,       0.15  ,  077-45625874
A010     ,     Santakumar   ,   Chennai       ,       0.14  ,  007-22388644
A012     ,     Lucida       ,   San Jose      ,       0.12  ,  044-52981425
A005     ,     Anderson     ,   Brisban       ,       0.13  ,  045-21447739
A001     ,     Subbarao     ,   Bangalore     ,       0.14  ,  077-12346674
A002     ,     Mukesh       ,   Mumbai        ,       0.11  ,  029-12358964
A006     ,     McDen        ,   London        ,       0.15  ,  078-22255588
A004     ,     Ivan         ,   Torento       ,       0.15  ,  008-22544166
A009     ,     Benjamin     ,   Hampshair     ,       0.11  ,  008-22536178

$ cat orders
   ORD_NUM ORD_AMOUNT ADVANCE_AMOUNT ORD_DATE  CUST_CODE       AGENT_CODE      
---------- ---------- -------------- --------- --------------- ------------
    200114       3500           2000 15-AUG-08 C00002          A008
    200122       2500            400 16-SEP-08 C00003          A004
    200118        500            100 20-JUL-08 C00023          A006
    200119       4000            700 16-SEP-08 C00007          A010
    200121       1500            600 23-SEP-08 C00008          A004
    200130       2500            400 30-JUL-08 C00025          A011
    200134       4200           1800 25-SEP-08 C00004          A005
    200108       4000            600 15-FEB-08 C00008          A004
    200103       1500            700 15-MAY-08 C00021          A005
    200105       2500            500 18-JUL-08 C00025          A011
    200109       3500            800 30-JUL-08 C00011          A010
    200101       3000           1000 15-JUL-08 C00001          A008
    200111       1000            300 10-JUL-08 C00020          A008
    200104       1500            500 13-MAR-08 C00006          A004
    200106       2500            700 20-APR-08 C00005          A002
    200125       2000            600 10-OCT-08 C00018          A005
    200117        800            200 20-OCT-08 C00014          A001
    200123        500            100 16-SEP-08 C00022          A002
    200120        500            100 20-JUL-08 C00009          A002
    200116        500            100 13-JUL-08 C00010          A009
    200124        500            100 20-JUN-08 C00017          A007
    200126        500            100 24-JUN-08 C00022          A002
    200129       2500            500 20-JUL-08 C00024          A006
    200127       2500            400 20-JUL-08 C00015          A003
    200128       3500           1500 20-JUL-08 C00009          A002
    200135       2000            800 16-SEP-08 C00007          A010
    200131        900            150 26-AUG-08 C00012          A012
    200133       1200            400 29-JUN-08 C00009          A002
    200100       1000            600 08-JAN-08 C00015          A003
    200110       3000            500 15-APR-08 C00019          A010
    200107       4500            900 30-AUG-08 C00007          A010
    200112       2000            400 30-MAY-08 C00016          A007
    200113       4000            600 10-JUN-08 C00022          A002
    200102       2000            300 25-MAY-08 C00012          A012