자료 출처 : http://oraclesqlpuzzle.hp.infoseek.co.jp/regex/


ab를 포함하지 않는, bc를 포함하지 않는,cd를 포함한 행을 검색한다.

대상 데이터
abcdefg
acbdefg
ab
bc
cd
cdxxabxxbc
abcd
cdab
axbxcdxxx

정규 표현
^(?!.*ab)(?!.*bc)(?=.*cd).*$
별해
^(?!(?=.*(ab|bc)))(?=.*cd).*$



룩어라운드... 멋진기능이야 ㅠㅠ

(?<= ...)  하위 표현식이 왼쪽에 매치될때
(?<! ...) 하위 표현식이 왼쪽에 매치되지 않을때
(?= ....) 하위 표현식이 오른쪽에 매치될때
(?! ...) 하위 표현식이 오른쪽에 매치되지 않을때

신고
Posted by naearu
TAG 정규식
Controlling PHP Output: Caching and compressing dynamic pages
(PHP 출력 제어하기 : 동적 페이지를 케싱하고 압축하기)

mod_gzip 은 gzip encoding을 지원하는 브라우저(IE Netscape 등)를 위한 IETF 표준에 따라 Gzip을 사용해서 정적 html 페이지를 압축하는 아파치 모듈입니다. mod_gzip은 다운로드시간은 4/5배 정도 더 빠르게 만들어 줍기 때문에 웹 서버에서 mod_gzip을 사용하길 강력 추천합니다. 그러나 Apache 1.x.x에서 모듈간의 필터링 메커니즘이 없기 때문에 PHP가 생성한 출력을 mod_zip으로 압축하는 것은 불가능합니다. 그렇기 때문에 직접 PHP로 압축엔진을 제작해 주어야합니다. 이 글에서는 PHP출력 제어 함수를 사용해서 페이지가 빨리! 뜨게 하는 방법을 설명합니다.

- PHP 출력 제어 함수란

PHP4의 좋은 점 중 하나는 PHP의 모든 출력을 버퍼에 담을 수 있다는 점입니다. 즉 출력이 직접 그 내용을 전송하기 전까지 브라우저로 전송되지 않게 할 수 있습니다. 이 함수는 header()나 setcookie()함수와 같이 내용이 전송되기 전에 호출되어야 하는 함수와 같이 사용됩니다. 그러나 이 용법은 출력 제어함수의 이점의 일부밖에 되지 않습니다.

void ob_start(void);

이 함수는 PHP 실행기에게 스크립트의 모든 출력을 내부 버퍼에 저장하게 합니다. ob_start()함수가 호출된 이후에는 이떠한 출력도 브라우저로 전송되지 않습니다.

string ob_get_contents(void);

이 함수는 내부 버퍼의 내용을 문자열로 리턴해 줍니다. 이 함수를 사용해서 버퍼에 축적된 출력을 (버퍼 기능을 off한 다음에) 읽어올 수 있습니다.

int ob_get_length(void);

버퍼에 축적된 내용의 길이를 리턴합니다.

void ob_end_clean(void);

버퍼 내용을 지우고 버퍼 기능을 off합니다. 내용을 브라우저로 전송하려면 이 함수를 사용해서 버퍼링 기능을 off해야합니다.

void ob_implicit_flush ([int flag])

이 함수는 자동 플러쉬(implicit flush)를 하게 합니다. 기본 값은 off입니다. 이 값이 on이면 모든 print/echo 함수가 호출될 때마다 flush가 실행되어서 즉시 브라우저로 전송되는 효과를 가져옵니다.

- PHP 출력을 압축하기 위해 출력 제어 함수 사용하기

출력을 압축하려면 PHP4를 컴파일 할 때 Zlib 확장기능을 추가해야 합니다.

1단계 : 출력 버퍼링을 초기화해줍니다.

<?php

ob_start();
ob_implicit_flush(0);

?>

2 단계 : 출력하고자 하는 내용을 print 든 echo든 뭐든지 간에 그냥 출력합니다. (브라우저에는 출력되지 않고 버퍼에 내용이 쌓입니다)

<?php

print("Hey this is a compressed output!");

?>

3단계 : 이렇게 버퍼에 쌓인 페이지를 읽어 옵니다.

<?php

$contents = ob_get_contents();
ob_end_clean();

?>

4단계 : 브라우저가 압축된 데이터를 지원하는지 검사합니다. 지원 여부는 브라우저가 서버에 request할 때 ACCETP_ENCODING 헤더(http 헤더)를 포함하고 있다는 점을 이용합니다. 즉 $HTTP_ACCEPT_ENCODING 변수에 "gzip, deflate"라는 내용이 있는지 검사합니다.

<?php

if(ereg('gzip, deflate',$HTTP_ACCEPT_ENCODING)) {
// 여기서 gzip으로 압축해서 내용을 전송
} else {
echo $contents;
}

?>

그렇게 복잡하지 않습니다. 이제 gzip으로 압축한 정보를 어떻게 생성하는지 한번 살펴봅시다.

(php.net에서 인용한 소스)

<?php

// Tell the browser that they are going to get gzip data
// Of course, you already checked if they support gzip or x-gzip
// and if they support x-gzip, you'd change the header to say
// x-gzip instead, right?
header("Content-Encoding: gzip");

// Display the header of the gzip file
// Thanks ck@medienkombinat.de!
// Only display this once
echo "x1fx8bx08x00x00x00x00x00";

// Figure out the size and CRC of the original for later
$Size = strlen($contents);
$Crc = crc32($contents);

// Compress the data
$contents = gzcompress($contents, 9);

// We can't just output it here, since the CRC is messed up.
// If I try to "echo $contents" at this point, the compressed
// data is sent, but not completely. There are four bytes at
// the end that are a CRC. Three are sent. The last one is
// left in limbo. Also, if we "echo $contents", then the next
// byte we echo will not be sent to the client. I am not sure
// if this is a bug in 4.0.2 or not, but the best way to avoid
// this is to put the correct CRC at the end of the compressed
// data. (The one generated by gzcompress looks WAY wrong.)
// This will stop Opera from crashing, gunzip will work, and
// other browsers won't keep loading indefinately.
//
// Strip off the old CRC (it's there, but it won't be displayed
// all the way -- very odd)
$contents = substr($contents, 0, strlen($contents) - 4);

// Show only the compressed data
echo $contents;

// Output the CRC, then the size of the original
gzip_PrintFourChars($Crc);
gzip_PrintFourChars($Size);

// Done. You can append further data by gzcompressing
// another string and reworking the CRC and Size stuff for
// it too. Repeat until done.

function gzip_PrintFourChars($Val) {
for ($i = 0; $i < 4; $i ++) {
echo chr($Val % 256);
$Val = floor($Val / 256);
}
}

?>

If you want to test it as a working example, the whole script is:

<?php

// Start the output buffer
ob_start();
ob_implicit_flush(0);

// Output stuff here...
print("I'm compressed!n");

$contents = ob_get_contents();
ob_end_clean();

// Tell the browser that they are going to get gzip data
// Of course, you already checked if they support gzip or x-gzip
// and if they support x-gzip, you'd change the header to say
// x-gzip instead, right?
header("Content-Encoding: gzip");

// Display the header of the gzip file
// Thanks ck@medienkombinat.de!
// Only display this once
echo "x1fx8bx08x00x00x00x00x00";

// Figure out the size and CRC of the original for later
$Size = strlen($contents);
$Crc = crc32($contents);

// Compress the data
$contents = gzcompress($contents, 9);

// We can't just output it here, since the CRC is messed up.
// If I try to "echo $contents" at this point, the compressed
// data is sent, but not completely. There are four bytes at
// the end that are a CRC. Three are sent. The last one is
// left in limbo. Also, if we "echo $contents", then the next
// byte we echo will not be sent to the client. I am not sure
// if this is a bug in 4.0.2 or not, but the best way to avoid
// this is to put the correct CRC at the end of the compressed
// data. (The one generated by gzcompress looks WAY wrong.)
// This will stop Opera from crashing, gunzip will work, and
// other browsers won't keep loading indefinately.
//
// Strip off the old CRC (it's there, but it won't be displayed
// all the way -- very odd)
$contents = substr($contents, 0, strlen($contents) - 4);

// Show only the compressed data
echo $contents;

// Output the CRC, then the size of the original
gzip_PrintFourChars($Crc);
gzip_PrintFourChars($Size);

// Done. You can append further data by gzcompressing
// another string and reworking the CRC and Size stuff for
// it too. Repeat until done.


function gzip_PrintFourChars($Val) {
for ($i = 0; $i < 4; $i ++) {
echo chr($Val % 256);
$Val = floor($Val / 256);
}
}

?>

(주 : ^^; 주석이 넘 길군요.....ㅠ,.ㅠ 회사일이 넘 많아서 번역 생략. 용서 ok?)

- PHP 출력을 caching하기

PHP4가 나오기 전에는 PHP3로 데이터베이스와 파일시스템 등에 걸리는 부하를 줄이기 위해 caching 메커니즘을 개발하는데 관심이 많았습니다. PHP4에서는 출력 버퍼링이라는 기능 대문에 훨씬 간단하게 구현할 수 있게 되었습니다.
다음은 그 간단한 예제입니다.

<?php

// 요청한 URI에 대한 cache 파일명을 임의로 생성
$cached_file=md5($REQUEST_URI);

// cache파일이 존재하지 않거나
// cache파일을 새로 만들어야 할 때에만 if절 내부 실행
if((!file_exists("/cache/$cached_file"))||(!is_valid("/cache/$cached_file"))) {
// is_valid함수는 cache파일을 검사하기 위해 자신이 직접 작성합니다.
// 즉 파일이 오래 되었는지...등의 검사를 해서 cache파일이 새로 작성되어야
// 하는지를 알 수 있도록 합니다.

ob_start();
ob_implicit_flush(0);

// 실제 이 페이지의 출력 부분.......

$contents = ob_get_contents();
ob_end_clean();

// cache파일 생성
$fil=fopen($cached_file,"w+");
fwrite($fil,$contents,$strlen($contents));
fclose($fil);
}

// cache 파일 출력
readfile($cached_file);

?>

이 예제는 간단한 예제입니다. 출력 버퍼링을 사용하면 꽤 진보된 내용 생성 시스템을 구축할 수 있습니다. 출력 버퍼링을 사용하면 XML과 XSLT를사용해서 XML제어에도 많은 이득을 볼 수 있습니다.

- 역자 주
여기서 서술한 내용은 여러분들의 gzip과 mod_gzip 출력 제어 함수 등의 내용을 공부하시는데 도움이 되었으면 하고 번역했습니다. 실제로 이 과정은 단 한 줄로 끝낼 수도 있고 php.ini등으로 자동으로 되게끔 셋팅할 수도 있습니다.
다음 라인을 스크립트 가장 처음에 추가하면 출력되는 정보가 자동으로 압축됩니다.

ob_start("ob_gzhandler");

또는 다음 라인을 php.ini에 넣으면 자동으로.... ^^;

output_handler = ob_gzhandler

출력 버퍼링이 대한 좋은 글은 http://www.zend.com/zend/art/buffering.php를 참고합니다.
신고
Posted by naearu


각 자리에
2 3 4 5 6 7 8 9 2 3 4 5
를 순서대로 곱하고..
다 더한다음에
11로 나누고
나눈 나머지를 11에서 뺀수를 맨뒤에 붙인다...10일경우 0

흐음..

어디보자~
검사하는 식을 만들어보면...

$ssn; //여기에 12자리 순수 숫자들로만 구성된 민번이 들어간다고 치고..
$key=array(2 ,3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5); 키가 되는 값들을 입력을 하고~

에~ 어디보자.. ssn을 어찌 쪼갤까...흐음..

sub_str($ssn,0,1); 이렇게 11자리 쪼개는거 말고 뭐 간단한거 없나?없나보군.. 젠장...

for($i=0;$i=<strlen($ssn);$i++){
$ssn_array[$i]=sub_str($ssn,$i,1);
}
이렇게 해서 한개씩 쪼개고...

for($i=0;$i=<strlen($ssn);$i++){
$sum+=$ssn_array[$i]*$key[$i];
}
이렇게 합을 구하고..
$tmp=$sum%11;
$check_key=11-$tmp;

이렇게 검사키를 만들고..

if($check_key==10)
   $check_key=0;
10일경우 처리해주고..

if($check_key==$ssn_array[12])
   echo "진짜민번";
else
  echo "가짜민번";

이렇게 되는건가?

흐음..

정리해서... 함수화 시키면..

function ssn_check($ssn){

$key=array(2 ,3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5);

for($i=0;$i=<13;$i++){
    $ssn_array[$i]=sub_str($ssn,$i,1);
}

for($i=0;$i<12;$i++){
    $sum+=$ssn_array[$i]*$key[$i];
}

$tmp=$sum%11;
$check_key=11-$tmp;

if($check_key==10)
   $check_key=0;

if($check_key==$ssn_array[12])
   return true;
else
   return false;
}

이렇게 되는데 맞나? ㄱ-;; 아님 말고..
이거뭐.. 조금만 바꾸면.. 민번 생성도 가능하네...(요샌 별 쓸모 없지만..)



신고
Posted by naearu


아.. 2일 고생했네 ㄱ-;;

생각보다 단순.. ㄱ-;;
아직 이미지와 태그를 어찌 보내야할지 막막하긴 하지만 ㄱ-;;
뭐;; 어찌 되것지뭐;; ㅋㅋ

function out_posting($entry){

  $blogid="0000"; // 블로그 api 고유번호
  $userID = "0000";  // 블로그 로그인 아이디
  $userPW = "0000";  //블로그 로그인 암호

  $subject   = $entry['tag'].$entry['title'];
  $body    = $entry['content'];
  $tag    = $entry['tag'];
  $cate    = $entry['category'];
  $reg_date   = gmstrftime("%Y%m%dT%H:%M:%S",time());
  $acceptComment  = $entry['acceptComment'];
  $acceptTrackback = $entry['acceptTrackback'];

 if($entry['visibility']<3)
  $published   = 0;
 else
  $published   = 1;


  $f = new xmlrpcmsg("metaWeblog.newPost",
  array(
  new xmlrpcval($blogid, "string"),
  new xmlrpcval($userID, "string"),
  new xmlrpcval($userPW, "string"),
  new xmlrpcval(
 
  array(

   //"category"=>new xmlrpcval($cate, "string"),  //카테고리
   //"mt_keywords"=>new xmlrpcval($tag, "string"),  // 태그 , 으로 구분
   "description"=>new xmlrpcval($body, "string"),  //내용
   "title"=>new xmlrpcval($subject, "string"),  //제목
   "mt_allow_comments"=>new xmlrpcval($acceptComment, "string"), //댓글허용 =1
   "mt_allow_pings"=>new xmlrpcval($acceptTrackback, "string"),  //트랙백허용 =1
   "dateCreated"=>new xmlrpcval($reg_date, "string")  //날짜

  ), "struct"),

  new xmlrpcval($published, "string") ) // 공개여부 공개 =1 비공개=0
  );
  $c=new xmlrpc_client("/api", "naearu.tistory.com", 80);
  $r=$c->send($f);

}




으아.. 만들어놓고 보니까 생각보다 단순해!!! 이런 줵일..

그렇게 머리싸매고 고생했는데 ㄱ-;;

애시당초 XML규격이 애매해서 ㄱ-;;

아직도 애매해서 태그와 카테고리가 좀 많이 고민이긴 한데.. 어쩌겟나.. 급한대로 써야지 ㅋ

일단.. 티스토리에 성공.. 이제 이글루스도.. 도전??ㅋ





으음 일단 태그까진 됏구..
카테고리와 이미지 올리는 방법만 알아내면 끝이로구나;;
신고
Posted by naearu

Open API에 관심을 갖게 되어 여기 저기 찾아보니 요새 많은 블로그들에서 범용으로 사용되는 프로토콜이 XMLRPC란 것을 알게 되었고, XMLRPC를 PHP에서 사용할 수 있도록 작성해 놓은 라이브러리를 찾을 수 있었다. XMLRPC for PHP 라이브러리는 소스포지의 한 프로젝트이며, 현재 2.2 버전까지 릴리즈가 되어 있다.

http://phpxmlrpc.sourceforge.net/

Open API에 관심을 갖게 만든건 미투데이의 블로그로 글 배달 서비스이다. 이 서비스를 받아들이기 위해서는 내 블로그에 XMLRPC 서버 기능을 추가해야 한다. 서버 기능이란 내 홈페이지로 request가 오면 그에 대한 처리를 하고 응답을 해 주는 기능을 말한다. 미투데이의 블로그로 글 배달 서비스의 경우 metaWeblog.newPost를 내 홈페이지에 보내게 되고, 서버 프로그램에서 그 request를 받아들여 DB에 글을 등록한 후 작성적으로 처리했다는 응답을 미투데이에 보내줘야 한다.

일단 미투데이의 블로그로 글 배달 서비스를 받기 위해선 blogger.getUsersBlogs 메소드와 metaWeblog.newPost 메소드에 대한 처리를 구현해야 한다. blogger.getUsersBlogs를 받으면 내 블로그에 대한 정보를 응답으로 보내줘야 하고, metaWeblog.newPost를 받았을 때는 글을 DB에 등록한 후 등록된 번호를 응답으로 보내줘야 한다.

참고로 FireFox의 부가기능인 ScribeFire에서는 위의 메소드 외에 metaWeblog.getCategories 메소드와 metaWeblog.getRecentPosts 메소드를 사용하여 블로그 정보를 얻어간다. 이 메소드들의 기능은 메소드 이름에 명확히 나타나 있기때문에 굳이 설명을 할 필요가 없어보인다.

이 밖에도 많은 메소드들이 존재하는데 다음의 페이지에서 간단한 정보를 얻을 수 있다. 어떤 메소드들이 있고 이 메소드에 대한 응답은 어떻게 하는지 간단하게 살펴볼 수 있다.

http://www.peopleaggregator.net/api/doc/peopleaggregator.html

이제 위의 메소드들에 대해서 서버 기능을 구현해주기만 하면 된다. XMLRPC for PHP 라이브러리는 체계적으로 잘 작성되어 있어서 어렵지 않게 구현할 수가 있다. 조금 살펴봐야 할 부분이 있다면 xmlrpcval class를 사용하는 방법 정도일 것이다. 물론 다큐먼트에 예제들이 잘 나와 있다.

xmlrpc.php라는 이름으로 서버 기능을 구현해 본다.

먼저 php파일 상단에 두 개의 파일을 인클루드 한다.

include "xmlrpc.inc";
include "xmlrpcs.inc";

그 다음 xmlrpc_server를 생성한다. 생성시 아규먼트로 메소드와 싱행할 함수의 쌍의 배열을 사용한다. 해당 메소드의 request를 받으면 콜백함수로써 등록된 함수가 실행되는 방식이다.

$s = new xmlrpc_server(
 array(
  "blogger.getUsersBlogs" => array("function", "blogger_getUsersBlogs"),
  "metaWeblog.getCategories" => array("function", "metaWeblog_getCategories"),
  "metaWeblog.getRecentPosts" => array("function", "metaWeblog_getRecentPosts"),
  "metaWeblog.newPost" => array("function", "metaWeblog_newPost")
 )
);

예를 들면, metaWeblog.newPost 요청을 서버에서 받은 경우 metaWeblog_newPost 함수가 실행되는 방식이다. metaWeblog_newPost 함수는 서버에서 구현해 주어야 하며 다음과 같이 작성할 수 있다.

function metaWeblog_newPost($msg)
{
 // $msg에는 클라이언트로부터 받은 XML 데이터가 포함되어 있다.
 
 $id = $msg->getParam(1);
 $id = $id->scalarVal(); // ID
 $password = $msg->getParam(2);
 $password = $password->scalarVal(); // Password

 // $id, $password를 비교해서 정상적인 접근인지 검사.

 // 응답할 XML 데이터 생성
 $value = new xmlrpcval(/* 응답할 데이터 */);

 return new xmlrpcresp($value); // 요청한 클라이언트로 응답
}

$msg에는 XML 데이터가 담겨있다. 각 값들을 파싱하는 함수들이 존재하므로 xmlrpcval 클래스 도움말을 참조하여 값들을 뽑아오면 된다. 요청을 잘 처리했으면 잘 처리했다는 응답을 요청한 클라이언트로 보내줘야 한다. xmlrpcresp 클래스를통해 응답을 해주게 되는데, 이 때 사용되는 $value값은 xmlrpcval 클래스를 사용하여 적당히 만들어줘야 한다.

지금까지의 작업으로 미투데이에서의 metaWeblog.newPost 요청을 처리할 수 있었다. 그런데 안타깝게도 한글이 깨져나오는 문제가 아직 존재한다. 오늘은 한글 문제를 해결하기 위해 골머리좀 쓰게 될 것 같다.

신고
Posted by naearu

12.3. 스트링 함수

 

  12.3.1. 스트링 비교 함수

 

스트링-값 함수는 그 결과 값의 길이가 max_allowed_packet 시스템 변수의 값 보다 클 경우에는, NULL을 리턴한다. Section 7.5.2, “서버 파라미터 튜닝하기를 참조할 것.


스트링 포지션(position)에서 연산을 하는 함수의 경우, 첫 번째 포지션은 숫자 1이 된다.

  • ASCII(str)

스트링 str 의 맨 왼쪽 문자의 숫자 값을 리턴한다. str 이 빈 스트링(empty string)일 경우에는 0 을 리턴한다. NULL if str NULL일 경우에는 NULL 을 리턴한다. ASCII()0 에서 255 사이의 숫자 값을 갖는 문자에 대해서 연산을 한다.

mysql> SELECT ASCII('2');

        -> 50

mysql> SELECT ASCII(2);

        -> 50

mysql> SELECT ASCII('dx');

        -> 100

ORD() 함수를 함께 참조할 것.

  • BIN(N)

N의 바이너리 값에 대한 스트링 표현식을 리턴하는데, 여기에서N (BIGINT) 숫자이다. 이것은 CONV(N,10,2)과 동일하다. N NULL일 경우에는 NULL을 리턴한다.

mysql> SELECT BIN(12);

        -> '1100'

  • BIT_LENGTH(str)

스트링 str 의 길이를 비트 단위로 리턴한다.

mysql> SELECT BIT_LENGTH('text');

        -> 32

  • CHAR(N,... [USING charset_name])

CHAR()은 각각의 인수 N 을 정수 형태로 해석을 하고 이러한 정수의 코드 값에 의해 주어지는 문자로 구성된 스트링을 리턴한다. NULL 값은 무시(skipped)된다.

mysql> SELECT CHAR(77,121,83,81,'76');

        -> 'MySQL'

mysql> SELECT CHAR(77,77.3,'77.3');

        -> 'MMM'

MySQL 5.0.15 이후 버전에서는,  255 보다 큰 CHAR() 인수는 여러 개의 결과 바이트로 변환된다. 예를 들면, CHAR(256)CHAR(1,0)와 같고, 그리고 CHAR(256*256) CHAR(1,0,0)과 같다:

mysql> SELECT HEX(CHAR(1,0)), HEX(CHAR(256));

+----------------+----------------+

| HEX(CHAR(1,0)) | HEX(CHAR(256)) |

+----------------+----------------+

| 0100           | 0100           |

+----------------+----------------+

mysql> SELECT HEX(CHAR(1,0,0)), HEX(CHAR(256*256));

+------------------+--------------------+

| HEX(CHAR(1,0,0)) | HEX(CHAR(256*256)) |

+------------------+--------------------+

| 010000           | 010000             |

+------------------+--------------------+

디폴트로는, CHAR()는 바이너리 스트링을 리턴한다. 주어진 문자 셋에 있는 스트링을 만들기 위해서는, USING 구문을 옵션으로 사용한다:

mysql> SELECT CHARSET(CHAR(0x65)), CHARSET(CHAR(0x65 USING utf8));

+---------------------+--------------------------------+

| CHARSET(CHAR(0x65)) | CHARSET(CHAR(0x65 USING utf8)) |

+---------------------+--------------------------------+

| binary              | utf8                           |

+---------------------+--------------------------------+

만일 USING을 사용하였는데도 그 결과 스트링이 주어진 문자 셋에 대해서 유효하지 않게 되면, 경고문이 나오게 된다. 또한, 만일 스트릭트(strict) SQL 모드를 활성화 한다면, CHAR() 의 결과 값은 NULL이 된다.

MySQL 5.0.15 이전 버전에서는, CHAR()는 연결 문자 셋에 있는 스트링을 리턴하며 USING 구문은 사용할 수 없게 된다. 또한, 각각의 인수는 모듈로(modulo) 256으로 해석이 되기 때문에, CHAR(256) CHAR(256*256)는 둘 다 CHAR(0)과 동일한 것이 된다.

  • CHAR_LENGTH(str)

스트링 str의 길이를 리턴한다. 다중 바이트 문자는 단일 문자로 계산(count) 된다. , 5개의 2 바이트 문자를 갖는 스트링에 대해서, LENGTH() 10을 리턴 하지만, CHAR_LENGTH()5를 리턴 한다.

  • CHARACTER_LENGTH(str)

CHARACTER_LENGTH()CHAR_LENGTH()과 동일하다.

  • CONCAT(str1,str2,...)

인수를 연결한 결과로 나오는 스트링을 리턴한다. 한 개 또는 그 이상의 인수를 가질 수 있다. 만일 모든 인수가 바이너리 스트링이 아니라면, 그 결과는 바이너리가 아닌 스트링이 된다. 만일 인수에 바이너리 스트링이 포함되어 있다면, 그 결과는 바이너리 스트링이 된다. 숫자 인수는 동일한 바이너리 스트링 형태로 변환된다; 만일 이렇게 변환되는 것을 원하지 않을 경우에는, 아래의 예문과 같이 명확하게 타입 캐스트(type cast)를 사용하면 된다:

SELECT CONCAT(CAST(int_col AS CHAR), char_col);

CONCAT()는 모든 인수가 NULL이 아니면 NULL을 리턴한다.

mysql> SELECT CONCAT('My', 'S', 'QL');

        -> 'MySQL'

mysql> SELECT CONCAT('My', NULL, 'QL');

        -> NULL

mysql> SELECT CONCAT(14.3);

        -> '14.3'

  • CONCAT_WS(separator,str1,str2,...)

CONCAT_WS()는 구분자를 사용하는 연결(Concatenate With Separator)을 나타내는 것이며 CONCAT()의 특수 형태이다. 첫 번째 인수는 나머지 인수들에 대한 구분자(separator)가 된다. 구분자는 연결되는 스트링 사이에 추가된다. 구분자는 스트링이 될 수 있다. 만일 구분자가 NULL 이면, 그 결과는 NULL이다.

mysql> SELECT CONCAT_WS(',','First name','Second name','Last Name');

        -> 'First name,Second name,Last Name'

mysql> SELECT CONCAT_WS(',','First name',NULL,'Last Name');

        -> 'First name,Last Name'

CONCAT_WS()는 빈 스트링(empty string)을 무시(skip)하지 않는다. 하지만, 구분자 인수 다음에 나오는 모든 NULL 값은 무시를 한다.

  • CONV(N,from_base,to_base)

서로 다른 문자 베이스(base)간의 숫자를 변환한다. from_base 에서 베이스 to_base로 변환된 숫자 N의 스트링 표현식을 리턴한다. 인수 중의 하나가 NULL이면 NULL을 리턴한다.인수 N 은 정수로 해석되지만, 정수 또는 스트링으로 지정될 수도 있다. 최소 베이스는 2 이고 최대 베이스는 36이다. 만일 to_base 가 음수라면, N 은 부호화된 숫자로 간주된다. 그렇지 않을 경우에는, N 은 부호 없는 숫자로 취급된다. CONV()64-비트 정밀도를 갖는다.

mysql> SELECT CONV('a',16,2);

        -> '1010'

mysql> SELECT CONV('6E',18,8);

        -> '172'

mysql> SELECT CONV(-17,10,-18);

        -> '-H'

mysql> SELECT CONV(10+'10'+'10'+0xa,10,10);

        -> '40'

  • ELT(N,str1,str2,str3,...)

만일N = 1이면, str1, N = 2이면, str2 을 리턴하는 방식. N 1 보다 작거나 또는인수의 숫자보다 많을 경우에는 NULL을 리턴한다. ELT()FIELD()의 보수(complement)이다.

mysql> SELECT ELT(1, 'ej', 'Heja', 'hej', 'foo');

        -> 'ej'

mysql> SELECT ELT(4, 'ej', 'Heja', 'hej', 'foo');

        -> 'foo'

  • EXPORT_SET(bits,on,off[,separator[,number_of_bits]])

bits에 있는 모든 비트 셋(bit set)에 대해서는, on 스트링을, 그리고 모든 리셋 비트에 대해서는, off 스트링을 리턴한다. bits 에 있는 비트는 오른쪽에서 왼쪽으로 검사된다 (낮은 순서에서 높은 순서 비트로). 스트링은 왼쪽에서 오른쪽으로 결과에 추가되는데, separator 스트링으로 구분이 된다 (디폴트 스트링은 콤마 문자,’). 검사가 되는 비트의 숫자는 number_of_bits로 주어진다 (디폴트는 64).

mysql> SELECT EXPORT_SET(5,'Y','N',',',4);

        -> 'Y,N,Y,N'

mysql> SELECT EXPORT_SET(6,'1','0',',',10);

        -> '0,1,1,0,0,0,0,0,0,0'

  • FIELD(str,str1,str2,str3,...)

str1, str2, str3, ... 리스트에 있는 str 의 인덱스(포지션)를 리턴한다. str을 찾을 수 없는 경우에는 0 을 리턴 한다.

만일 FIELD()에 대한 모든 인수가 스트링이라면, 모든 인수는 스트링으로 비교된다. 만일 모든 인수가 숫자일 경우에는 숫자로 비교가 된다. 그렇지 않은 경우라면, 인수들은 두 번 (double) 비교가 된다.

만일 str NULL이라면, 리턴 값은 0 이 되는데, 그 이유는 NULL 은 어떤 값과도 등식 비교가 되지 않기 때문이다. FIELD()ELT()의 보수(complement)이다.

mysql> SELECT FIELD('ej', 'Hej', 'ej', 'Heja', 'hej', 'foo');

        -> 2

mysql> SELECT FIELD('fo', 'Hej', 'ej', 'Heja', 'hej', 'foo');

        -> 0

  • FIND_IN_SET(str,strlist)

만일 스트링 str N 의 서브 스트링으로 구성된 스트링 리스트 strlist 에 있는 것이라면, 1의 범위에 있는 값을 N 에 리턴한다. 하나의 스트링 리스트는 콤마 문자로 구분된 서브 스트링들로 구성된 스트링이다. 만일 첫 번째 인수가 상수 스트링이고 두 번째 인수가 타입 SET의 컬럼이라면, FIND_IN_SET() 함수는 비트 산술식을 사용하기 위해서 최적화가 된다. 만일 str strlist에 없거나 또는 strlist가 빈 스트링이라면, 0을 리턴한다. NULL if만일 인수 중의 하나가 NULL이라면, NULL을 리턴한다. 만일 첫 번째 인수가 콤마 문자를 가지고 있다면, 이 함수는 제대로 동작을 하지 않는다.

mysql> SELECT FIND_IN_SET('b','a,b,c,d');

        -> 2

  • FORMAT(X,D)

숫자 X 의 포맷을 '#,###,###.##' 형태로 만들고, D의 소수점 뒷자리에서 절사(round)를 하고, 그 결과를 스트링으로 리턴한다. 만일 D 0 이면, 그 결과는 소수점 또는 분수 부분을 갖지 않는다.

mysql> SELECT FORMAT(12332.123456, 4);

        -> '12,332.1235'

mysql> SELECT FORMAT(12332.1,4);

        -> '12,332.1000'

mysql> SELECT FORMAT(12332.2,0);

        -> '12,332'

  • HEX(N_or_S)

만일N_or_S 이 숫자라면, N에 대한 16진수 값에 해당하는 스트링 표현을 리턴하는데, 여기에서 N (BIGINT) 숫자가 된다. 이것은 CONV(N,10,16)과 동일하다.

만일 N_or_S 이 스트링 이라면, N_or_S 에 대한 16진수 스트링 표현식을 리턴하는데, N_or_S 에 있는 각각의 문자는 2개의 16진수 숫자로 변환된다.

mysql> SELECT HEX(255);

        -> 'FF'

mysql> SELECT 0x616263;

        -> 'abc'

mysql> SELECT HEX('abc');

        -> 616263

  • INSERT(str,pos,len,newstr)

str 의 포지션 pos 에서 시작하는 서브 스트링을 len 문자 길이만큼 스트링 newstr로 변경시켜서 str 을 리턴한다. 만일 pos 가 스트링의 길이 안에 있지 않다면, 원래의 스트링을 리턴한다. 만일 len 의 범위가 스트링의 나머지 길이 범위 내에 있지 않다면, 포지션 pos  이후의 나머지 스트링을 대체 시킨다. 만일 어떤 인수가 NULL 이면, NULL을 리턴한다.

mysql> SELECT INSERT('Quadratic', 3, 4, 'What');

        -> 'QuWhattic'

mysql> SELECT INSERT('Quadratic', -1, 4, 'What');

        -> 'Quadratic'

mysql> SELECT INSERT('Quadratic', 3, 100, 'What');

        -> 'QuWhat'

이 함수는 다중 바이트에서도 동작을 한다.

  • INSTR(str,substr)

str 에서 서브 스트링 substr 가 처음으로 나오는 포지션을 리턴한다. 이것은 LOCATE()에서 두 개의 인수를 사용하는 것과 동일한 결과를 리턴 하지만, 인수들의 순서는 반대가 된다.

mysql> SELECT INSTR('foobarbar', 'bar');

        -> 4

mysql> SELECT INSTR('xbar', 'foobar');

        -> 0

이 함수는 다중 바이트에서도 동작을 하며, 최소 하나의 인수가 바이너리 스트링일 경우에만 문자 크기를 구분한다.

  • LCASE(str)

LCASE()LOWER()와 동의어 이다.

  • LEFT(str,len)

스트링 str에서 가장 왼쪽으로부터 len 개의 문자를 리턴한다.

mysql> SELECT LEFT('foobarbar', 5);

        -> 'fooba'

  • LENGTH(str)

str의 길이를 바이트 단위로 리턴한다. 다중 바이트 문자는 다중 바이트로 계산 (count)된다. 이것은 2 바이트 문자가 5개 있는 스트링의 경우, LENGTH() 10을 리턴하는 반면에, CHAR_LENGTH()5를 리턴한다는 것을 의미한다.

mysql> SELECT LENGTH('text');

        -> 4

  • LOAD_FILE(file_name)

파일을 읽은 다음에 파일의 내용물을 스트링으로 리턴한다. 이 함수를 사용하기 위해서는, 파일은 반드시 서버 호스트에 있어야 하며, 그 파일에 대한 경로 이름을 전체적으로 지정해야 하며, 그리고 FILE 권한을 가져야 한다. 그 파일은 모든 사용자에게 읽힐 수 있어야 하며 파일의 크기는 max_allowed_packet 바이트 보다는 작아야 한다.

만일 파일이 존재하지 않거나 또는 위의 조건 중에 하나로 인해 파일을 읽을 수가 없게 된다면, 이 함수는 NULL을 리턴한다.

MySQL 5.0.19 이후 버전에서는, character_set_filesystem 시스템 변수가 리터럴 스트링으로 주어진 파일 이름에 대한 해석을 제어한다.

mysql> UPDATE t

            SET blob_col=LOAD_FILE('/tmp/picture')

            WHERE id=1;

  • LOCATE(substr,str), LOCATE(substr,str,pos)

첫 번째 신텍스는 str 에서 서브 스트링 substr 가 처음으로 나오는 포지션을 리턴한다. 두 번째 신텍스는, 포지션 pos에서 시작을 해서, str 에서 서브 스트링 substr 가 처음으로 나오는 포지션을 리턴한다. substr str에 존재하지 않을 경우에는, 0을 리턴한다.

mysql> SELECT LOCATE('bar', 'foobarbar');

        -> 4

mysql> SELECT LOCATE('xbar', 'foobar');

        -> 0

mysql> SELECT LOCATE('bar', 'foobarbar', 5);

        -> 7

이 함수는 다중 바이트에서도 동작을 하며, 인수 중에서 최소 하나라도 바이너리 스트링일 경우에만 문자 크기를 구분한다.

  • LOWER(str)

현재 (current) 문자 셋 매핑에 따라서 스트링 str 의 모든 문자를 소문자로 변경 시켜서 리턴한다. 디폴트는 latin1 (cp1252 West European).

mysql> SELECT LOWER('QUADRATICALLY');

        -> 'quadratically'

이 함수는 다중 바이트에서도 동작을 한다.

  • LPAD(str,len,padstr)

왼쪽에 스트링 padstr 를 집어 넣어서 문자의 길이를 len 만큼 되도록 한 스트링 str 을 리턴한다. 만일 str len 보다 길다면, 리턴 값은 len 길이 만큼 줄어 든다.

mysql> SELECT LPAD('hi',4,'??');

        -> '??hi'

mysql> SELECT LPAD('hi',1,'??');

        -> 'h'

  • LTRIM(str)

스트링 앞에 있는 스페이스를 없앤 스트링 str 를 리턴한다.

mysql> SELECT LTRIM('  barbar');

        -> 'barbar'

이 함수는 다중 바이트에서도 동작을 한다.

  • MAKE_SET(bits,str1,str2,...)

bits 셋에 대응되는 비트를 가지고 있는 스트링으로 구성된 셋 값 (콤마 문자로 구분된 서브 스트링을 가지고 있는 스트링)을 리턴한다. str1은 비트 0에 대응되고, str2 1에 대응되며, 계속 이런 식으로 대응이 된다. str1, str2, ... 에 있는 NULL 값은 결과에 따라 나오지 않는다.

mysql> SELECT MAKE_SET(1,'a','b','c');

        -> 'a'

mysql> SELECT MAKE_SET(1 | 4,'hello','nice','world');

        -> 'hello,world'

mysql> SELECT MAKE_SET(1 | 4,'hello','nice',NULL,'world');

        -> 'hello'

mysql> SELECT MAKE_SET(0,'a','b','c');

        -> ''

  • MID(str,pos,len)

MID(str,pos,len)SUBSTRING(str,pos,len)과 동의어 이다.

  • OCT(N)

N 8진 값에 해당하는 스트링 표현식을 리턴하는데, 여기에서 N (BIGINT) 번호가 된다. 이것은 CONV(N,10,8)과 같다. 만일 N NULL이면, NULL을 리턴한다.

mysql> SELECT OCT(12);

        -> '14'

  • OCTET_LENGTH(str)

OCTET_LENGTH()LENGTH()과 동의어 이다.

  • ORD(str)

만일 If the leftmost character of the string스트링 str 의 가장 왼쪽의 문자가 다중 바이트 문자라면, 그 문자에 대한 코드를 리턴하는데, 그 값은 아래의 공식을 사용해서 얻어낸다:

  (1st byte code)

+ (2nd byte code × 256)

+ (3rd byte code × 2562) ...

만일 가장 왼쪽의 문자가 다중 바이트 문자가 아니라면, ORD()ASCII() 함수와 같은 값을 리턴한다.

mysql> SELECT ORD('2');

        -> 50

  • POSITION(substr IN str)

POSITION(substr IN str)LOCATE(substr,str)과 동의어 이다.

 

  • QUOTE(str)

SQL 명령문에서 이스케이프된 데이터 값으로 사용할 수 있는 결과를 만들기 위해 스트링에 인용 부호를 준다. 만일 인수가 NULL이면, 리턴 값은 인용 부호가 없는 단어 “NULL” 이 나오게 된다.

mysql> SELECT QUOTE('Don\'t!');

        -> 'Don\'t!'

mysql> SELECT QUOTE(NULL);

        -> NULL

  • REPEAT(str,count)

count 횟수 만큼 반복된 스트링 str 으로 구성된 스트링을 리턴한다. 만일 count 1 보다 작을 경우에는, 빈 스트링을 리턴한다. str 또는 count NULL이라면, NULL을 리턴한다

mysql> SELECT REPEAT('MySQL', 3);

        -> 'MySQLMySQLMySQL'

  • REPLACE(str,from_str,to_str)

스트링 from_str 가 나온 부분을 모두 스트링 to_str로 대체해서 스트링 str 을 리턴한다.               REPLACE()from_str에 대한 검색을 할 때 문자 크기를 구분해서 매칭을 실행한다.

mysql> SELECT REPLACE('www.mysql.com', 'w', 'Ww');

        -> 'WwWwWw.mysql.com'

이 함수는 다중 바이트에서도 동작을 한다.

  • REVERSE(str)

문자의 순서를 역순으로 헤서 스트링 str 을 리턴한다.

mysql> SELECT REVERSE('abc');

        -> 'cba'

이 함수는 다중 바이트에서도 동작을 한다.

  • RIGHT(str,len)

str에서 오른쪽으로부터 len 문자 만큼을 리턴한다.

mysql> SELECT RIGHT('foobarbar', 4);

        -> 'rbar'

이 함수는 다중 바이트에서도 동작을 한다.

  • RPAD(str,len,padstr)

스트링 padstr 를 오른쪽에 집어 넣어서 len 문자 길이 만큼 str을 만들어서 리턴한다. 만일 str len 보다 길다면, 리턴 값은 len 문자 만큼 짧아진다.

mysql> SELECT RPAD('hi',5,'?');

        -> 'hi???'

mysql> SELECT RPAD('hi',1,'?');

        -> 'h'

이 함수는 다중 바이트에서도 동작을 한다.

  • RTRIM(str)

스트링 str에서 뒤에 붙어 있는 스페이스 문자를 없앤 스트링을 리턴한다.

mysql> SELECT RTRIM('barbar   ');

        -> 'barbar'

이 함수는 다중 바이트에서도 동작을 한다.

  • SOUNDEX(str)

Str의 사운덱스(soundex) 스트링을 리턴한다. 거의 같은 소리가 나는 두 개의 스트링은 고유의 사운덱스 스트링을 가져야 한다. 표준 사운덱스 스트링은 4 문자 길이가 되지만, SOUNDEX() 함수는 임의의 길이 스트링을 리턴한다. 여러분은 표준 사운덱스 스트링을 얻기 위해서 결과 값에 SUBSTRING()을 사용할 수가 있다. str에 있는 문자 중에 알파벳이 아닌 것들은 모두 무시가 된다. A-Z 범위를 벗어나는 모든 국제 문자들은 모두 모음으로 취급된다.

mysql> SELECT SOUNDEX('Hello');

        -> 'H400'

mysql> SELECT SOUNDEX('Quadratically');

        -> 'Q36324'

  • expr1 SOUNDS LIKE expr2

이것은 SOUNDEX(expr1) = SOUNDEX(expr2)과 같다.

  • SPACE(N)

N 개의 스페이스 문자로 구성된 스트링을 리턴한다.

mysql> SELECT SPACE(6);

        -> '      '

  • SUBSTRING(str,pos), SUBSTRING(str FROM pos), SUBSTRING(str,pos,len), SUBSTRING(str FROM pos FOR len)

len 인수가 없는 형태는 포지션 pos에서 시작을 하는 서브 스트링을 스트링 str 에서 리턴 한다. len 인수를 가지고 있는 형태는 포지션 pos에서 시작을 해서 서브 스트링 len 문자를 리턴한다. FROM을 사용하는 형태는 표준 SQL 신텍스이다. pos의 값으로 음수를 사용하는 것도 가능하다. 음수를 사용할 경우에는, 서브 스트링의 시작점이 스트링의 처음이 아닌 끝에서부터 pos 문자 위치가 된다. 음수 값은 이 함수의 어떤 형태에서도 사용이 가능하다.

mysql> SELECT SUBSTRING('Quadratically',5);

        -> 'ratically'

mysql> SELECT SUBSTRING('foobarbar' FROM 4);

        -> 'barbar'

mysql> SELECT SUBSTRING('Quadratically',5,6);

        -> 'ratica'       

mysql> SELECT SUBSTRING('Sakila', -3);

        -> 'ila'       

mysql> SELECT SUBSTRING('Sakila', -5, 3);

        -> 'aki'

mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);

        -> 'ki'

이 함수는 다중 바이트에서도 동작을 한다.

만일 len 1 보다 작으면, 그 결과는 빈 스트링이 된다.

SUBSTR()SUBSTRING()과 동일하다.

  • SUBSTRING_INDEX(str,delim,count)

구분자 (delimiter) delimcount 만큼 나오기 전에 스트링 str 에서 서브 스트링을 리턴한다. 만일 count 가 양수 (positive)라면, 마지막 구분자의 왼쪽에 있는 모든 것들이 리턴된다 (왼쪽부터 계산이 됨). 만일 count 가 음수일 경우에는, 마지막 구분자의 오른쪽에 있는 모든 것들이 리턴된다 (오른쪽부터 계산됨). SUBSTRING_INDEX()delim에 대한 검색을 할 때 문자의 크기를 구분한다.

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', 2);

        -> 'www.mysql'

mysql> SELECT SUBSTRING_INDEX('www.mysql.com', '.', -2);

        -> 'mysql.com'

이 함수는 다중 바이트를 지원한다.

  • TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str), TRIM([remstr FROM] str)

스트링 str 를 모든 remstr 접두사 (prefixes) 또는 접미사를 제거한 상태로 리턴한다. 만일 BOTH, LEADING, 또는 TRAILING 중의 어느 것도 주어지지 않는다면, BOTH가 주어진 것으로 간주된다. remstr 는 선택 사항이며, 만일 지정되지 않을 경우에는, 스페이스가 제거된다.

mysql> SELECT TRIM('  bar   ');

        -> 'bar'

mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');

        -> 'barxxx'

mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');

        -> 'bar'

mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');

        -> 'barx'

이 함수는 다중 바이트를 지원한다.

  • UCASE(str)

UCASE()UPPER()와 동의어이다.

  • UNHEX(str)

HEX(str)와는 반대 연산을 실행한다. , 이 함수는 인수에 있는 각각의 16진수를 숫자로 해석을 하고 그 숫자에 대응하는 문자로 변환을 시킨다. 그 결과로 나오는 문자들은 바이너리 스트링으로 리턴된다.

mysql> SELECT UNHEX('4D7953514C');

        -> 'MySQL'

mysql> SELECT 0x4D7953514C;

        -> 'MySQL'

mysql> SELECT UNHEX(HEX('string'));

        -> 'string'

mysql> SELECT HEX(UNHEX('1267'));

        -> '1267'

  • UPPER(str)

Returns 스트링 str 를 현재의 (current) 문자 셋 매핑에 따라서 대문자로 변환이 된 모든 문자와 함께 리턴한다. 디폴트는 latin1 (cp1252 West European).

mysql> SELECT UPPER('Hej');

        -> 'HEJ'

이 함수는 다중 바이트를 지원한다.

신고
Posted by naearu

블로그들의 방문자수를 가져오는 프로그램을 짜야할 일이 생겨서..

블로그들에 프로그램으로 접속을 시도했다!!



얼래? 몇번하다보니 알았는데..이거..카운트가 올라가네??

설마 설마 하면서 새로고침을 몇번해주니까;;

얼라리랍쇼?

카운트가 쭉쭉올라가네? 막힘없는건가?

사용자 삽입 이미지
그래서 심심해서..
10초당 한번씩 리로드 되게 해놓고..
걍 두고 회사갓다 오니까..투데이가 만명이 넘었다 ㄱ-;;

(만명채웟는데 그새 3명이 들어왓네;;)

평소에 끽해야;; 300명? 많이오면 천명정도?엿던것을;; 그냥.. 10000명..워...참으로 대단하다 ㄱ-;;;

카운터좀 올리려고.. 이상한짓몇번 하긴 했지만;; 이걸로써.. 그냥.. 무의미해져버렷다..
자.. 대략 계산을 해봅시다..
이걸 켜놓고 나간게.. 아침..8시쯤..
끄고 확인한게 9시30분..
1분당..6명이 들어오는 셈이니까..
6x60x13=4,680
대략.. 4천명? 엥?? 계산이 이상한가??? ㄱ-;;
아.. 뭔가.. 셋팅미스인듯..10ㅊ당으로 돌아선 절대 만명이 안되는군;;
그렇다고 설마. 5천명이 하루에 왓다고 할리도 없고;;
뭐; 여튼..
생각해보면.. 1초당한번이면..13시간에 46,800이다.. ㄱ-; 이게 어디 하루치 카운터인가!!!
내 토탈 카운트보다 많다;;
뭐.. 소스를 손보면야.. 한시간안에 만명도 채우겟지만;;

이미 ㄱ-; 후...
file 이 네글자의 위력으로 하루 카운트가 만이 넘는다는게;; 참;; 신기하군하;;

심심한데 2만 넘겨놓을까;; 오늘만? ㅋ


....
해보고 싶으신분은 말씀하삼.. 친히 초당 한방씩 날리는 코드로 써드리겟심 ㄱ-;



신고
Posted by naearu

PHP에서 소수점 버림함수는 floor()입니다.

floor 버림
floor(4.3);  // 4
floor(9.999); // 9

ceil 올림
ceil(4.3);    // 5
ceil(9.999);  // 10

round반올림
round(3.4);        // 3
round(3.5);        // 4
round(3.6);        // 4
round(3.6, 0);      // 4
round(1.95583, 2);  // 1.96
round(1241757, -3); // 1242000
round(5.045, 2);    // 5.05
round(5.055, 2);    // 5.06


신고
Posted by naearu
유져 생성 CREATE USER 'Username'@'localhost' IDENTIFIED BY '********';

유져 DB권한 설정. GRANT ON `channel` . * TO 'Username'@'localhost' WITH GRANT OPTION ;
 
ALL PRIVILEGES 데이터/구조에 관한 모든 권한
 
USAGE // 데이터/구조에 관한 권한 없음.

DB 데이터에 관한 구조
SELECT ,
 INSERT ,
UPDATE ,
DELETE ,

DB 구조에 관한 구조. CREATE , DROP , REFERENCES , INDEX , ALTER , CREATE TEMPORARY TABLES , LOCK TABLES , CREATE VIEW , SHOW VIEW , CREATE ROUTINE, ALTER ROUTINE , EXECUTE DB 관리 권한 LOCK TABLES REFERENCES 계정생성권한 WITH GRANT OPTION ; 계정생성권한을 제외하고 나머지는 DB권한 부분에 들어감. `channel` . * `channel` 이라는 데이터베이스의 모든 테이블에관한 권한. 'Username'@'localhost' 'Username'이라는 유져의 'localhost'의 권한.
신고
Posted by naearu

계산 함수와 함께 각 그룹에 대해 하나의 행과 하나의 요약 정보를 생성


SELECT field_name From table_name


     WHERE search_conditions


          GROUP BY [ALL] aggregate_free_expression [, aggregate_free_expression...]]


          [HAVING search conditions]



- GROUP BY : 선택된 테이블의 각 그룹에 대한 요약 정보를 생성


- HAVING : 결과 행들에 대해 제약을 가함, 조건에 맞지 않는 그룹들을 제외한다.





* ANSI 표준 SQL에서의 요구사항


- fields_name 에 있는 모든 컬럼들은 반드시 GROUP BY 절에 나타나야 한다.


- HAVING 에 있는 컬럼은 반드시 하나의 값을 반환해야 한다.


- HAVING 을 포함한 질의는 반드시 GROUP BY 절을 포함해야 한다.



* Transact - SQL 에서는 ANSI 표준 SQL 보다 많은 옵션을 제공한다.


- GROUP BY 절은 수식을 포함할 수 있다.


- GOURP BY ALL은 WHERE절에서 제외된 그룹까지도 포함한다.


- ALL 은 SELECT문이 WHERE절을 포함할 때만 의미가 있다.





ex)

select title_id, copies_sold = sum(qty) from sales group by title_id


select title_id, copies_sold = sum(qty) from sales

    

     where ord_date between '1/1/1994' and '12/31/1994' group by ALL title_id

신고
Posted by naearu

◈ ROLLUP operator


  - ROLLUP구문은 GROUP BY절과 같이 사용 되며, GROUP BY절에 의해서 그룹 지어진
    집합결과에 대해서 좀 더 상세한 정보를 반환하는 기능을 수행합니다.

  - SELECT절에 ROLLUP을 사용함으로써 보통의 select된 데이터와 그 데이터의
    총계를 구할 수 있습니다.


※ 우선 아주 간단한 예제부터 살펴 보겠습니다.
   (scott유저의 emp테이블을 가지고 테스트 했습니다.)


-- Group By를 사용해서 직업별로 급여 합계를 구하는 예제 입니다.

SELECT job, SUM(sal)
FROM emp
GROUP BY job


JOB          SUM(SAL)
---------- ----------
ANALYST          600
CLERK              3200
MANAGER        33925
PRESIDENT      5000
SALESMAN      4000


-- 아래 SQL문은 위의 예제에 ROLLUP구문을 사용해서 직업별로 급여 합계를 구하고
   총계를 구하는 예제 입니다.

SELECT job, SUM(sal)
FROM emp
GROUP BY ROLLUP(job)
 

JOB          SUM(SAL
---------- ----------
ANALYST          6000
CLERK              3200
MANAGER        33925
PRESIDENT       5000
SALESMAN       4000
                       52125   --> 급여 합계에 대한 총계가 추가 되었습니다.




우선 간단하게 ROLLUP  Operator의 예제를 살펴보았습니다.
조금더 복잡한(?) 예제를 하나더 해보면은요..

-- 부서의 직업별로 인원수와 급여 합계를 구하는 예제를 하나더 해보겠습니다.

-- 일반적인 Group By절을 사용해서 SQL문을 구현해보면은요.. 아래와 같이 하면 되겠죠..

SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_count
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY b.dname, a.job


DNAME       JOB               SAL  EMP_COUNT
----------  ---------- ---------- ----------
ACCOUNTING  CLERK               1300          1
ACCOUNTING  MANAGER          2450          1
ACCOUNTING  PRESIDENT        5000          1
RESEARCH    ANALYST            6000          2
RESEARCH    CLERK                1900          2
RESEARCH    MANAGER           2975          1
SALES       MANAGER              28500          1
SALES       SALESMAN             4000          3


-- 결과를 보면은요..  부서별로 인원이 몇명이고, 또 급여합계가 얼마가 되는지 한눈에 보이지 않죠...
   일일이 부서에 해당하는 직업별 급여와 사원수를 일일이 더해야 되죠..

-- 이런 경우 ROLLUP  Operator를 적용해서 구현을 하면은 부서별 급여합계와 사원 총수를
   쉽게 볼 수 있습니다...

SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_count
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY ROLLUP(b.dname, a.job)


DNAME      JOB               SAL  EMP_COUNT
---------- ---------- ---------- ----------
ACCOUNTING CLERK              1300          1
ACCOUNTING MANAGER          2450          1
ACCOUNTING PRESIDENT        5000          1
ACCOUNTING                         8750          3  -->  ACCOUNTING 부서의 급여합계와 전체 사원수..
RESEARCH   ANALYST            6000          2
RESEARCH   CLERK                1900          2
RESEARCH   MANAGER           2975          1
RESEARCH                            10875          5 -->  RESEARCH 부서의 급여합계와 전체 사원수..
SALES      MANAGER              28500          1
SALES      SALESMAN             4000          3
SALES                                  32500          4 -->  SALES부서의 급여합계와 전체 사원수..
                                            52125         12 ->  전체 급여 합계와 전체 사원수


위와 같이 ROLLUP Operator을 일반적인 누적에 대한 총계를 구할때 사용하면 아주 편리하게
사용 할 수 있습니다.
 
 
 
 
 
 
 
 
 -   
 SELECT NVL(DECODE(B.NO, '1', DNAME), '총계') DNAME,
SUM(CLERK) CLERK,
SUM(MANAGER) MANAGER,
SUM(ETC) ETC,
SUM(DEPT_SAL) DEPT_SAL
FROM (
SELECT B.DNAME, A.CLERK, A.MANAGER, A.ETC, A.CLERK + A.MANA
GER + A.ETC DEPT_SAL
FROM (
SELECT DEPTNO,
SUM(DECODE(JOB,'CLERK',SAL)) CLERK,
SUM(DECODE(JOB,'MANAGER',SAL)) MANAGER,
SUM(DECODE(JOB,'MANAGER',0,'CLERK',0,SAL)) ETC
FROM EMP
GROUP BY DEPTNO
) A, DEPT B
WHERE A.DEPTNO = B.DEPTNO ) A,
(SELECT '1' NO FROM DUAL
UNION ALL
SELECT '2' FROM DUAL) B
GROUP BY DECODE(B.NO, '1',A.DNAME);

위 처럼 오라클에서 지원하는 함수를 이용하지 않고 만들어 봤어요..
참조 하세요.
 
 
 
 -   
 SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_co
unt
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY b.dname, a.job

분석해 볼까여
1.select;
2.from
3.where
4.group

2.테이블 두개가 메모리에 적제가 되겠죠
3.조건에 의해 deptno 을 기준으로 하나의 테이블로 정리 되겠죠
그다음은 4. 가 계산되는데
여기서 4.가 없다고 가정하면
1.로 가서 결국 하나의 행이 결과값으로 도출될 것입니다. 그룹함수에 의해서
총합과 행의 총갯수가 반환되겠죠
그럼 다시 되돌아가서
4.group by 절이 계산을 하게 되는데 우선 b.dname만 있다면 몇개의 레코드가 반환될까여 부서명이
4개라면.. 4개의 레코드가 반환되겠죠(단 4개의 부서가 데이타에 존재한다면)
그 다음에 a.job 까지(직업은 3개라고 가정하면) 두개의 조건이 주어졌습니다.
그럼 몇개의 레코드가 반환될까여 12개의 레코드가 반환될까여????

이번에는 문장을 분석해서 SQL을 작성해 볼까여 (위 강의가 기준)
부서의 직업별로 인원수와 급여 합계를 구하라

키포인트 인원수와 급여합계입니다.
여기서 그룹함수가 사용된다는 것을 알수 있고 GROUP BY절을 사용해야 된다는 것도 알수가 있습니다.
형식은
1.SELECT
2.TABLE
3.WHERE
4.GROUP BY
로 형식이 가추어 지고
1. 컬럼은 4개가 되고 그룹함수 SUM()가 COUNT()가 들어가고여
2. 테이블은 위 강의가 기준이니까 2개이고여
3. 자연스럽게 JOIN 이 일어나겠네여 무슨 조인일까여????
4. GROUP BY절에서 부서와 직업이 GROUP으로 묶여지겠네여...
SQL을 작성하면 위와 같겠지여

 
 
 




◈ CUBE operator


 ※ CUBE강좌를 보시기 전에 바로 위에 있는 ROLLUP강좌를 꼭 봐주세요..
 
 ROLLUP 강좌예제 중에서 아래 SQL문 예제를 가지고 CUBE강좌를 진행 하려고 합니다.

====================  ROLLUP 강좌의 예제입니다.  =======================

SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_count
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY ROLLUP(b.dname, a.job)


DNAME      JOB               SAL  EMP_COUNT
---------- ---------- ---------- ----------
ACCOUNTING CLERK              1300          1
ACCOUNTING MANAGER          2450          1
ACCOUNTING PRESIDENT        5000          1
ACCOUNTING                         8750          3  -->  ACCOUNTING 부서의 급여합계와 전체 사원수..
RESEARCH   ANALYST            6000          2
RESEARCH   CLERK                1900          2
RESEARCH   MANAGER           2975          1
RESEARCH                            10875          5 -->  RESEARCH 부서의 급여합계와 전체 사원수..
SALES      MANAGER              28500          1
SALES      SALESMAN             4000          3
SALES                                  32500          4 -->  SALES부서의 급여합계와 전체 사원수..
                                            52125         12 ->  전체 급여 합계와 전체 사원수

=========================================================================


위의 SQL의 결과를 보면 부서별로 각 직업에 해당하는 급여와 사원수를 볼 수 있습니다.

하지만 부서별로 각 직업의 급여와 사원수, 그리고 또 각 직업별로 급여 합계와 사원수를
보기 위해서는 두개의 ROLLUP을 사용해서 SQL문을 작성해야 합니다.

아래와 같이 되겠죠..
 

SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_count
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY ROLLUP(b.dname, a.job)
UNION
SELECT ' ', job, SUM(sal) sal, COUNT(empno) emp_count
FROM emp
GROUP BY ROLLUP(job)
 
DNAME      JOB               SAL  EMP_COUNT
---------- ---------- ---------- ----------
ACCOUNTING CLERK               1300          1
ACCOUNTING MANAGER          2450          1
ACCOUNTING PRESIDENT        5000          1
ACCOUNTING                         8750          3
RESEARCH    ANALYST           6000          2
RESEARCH    CLERK               1900          2
RESEARCH    MANAGER          2975          1
RESEARCH                           10875          5
SALES          MANAGER         28500          1
SALES          SALESMAN         4000          3
SALES                                 32500          4   => 요기 까지는 첫 번째 ROLLUP를 이용해서 구하고요
                   ANALYST          6000          2
                   CLERK              3200          3
                   MANAGER         33925          3
                   PRESIDENT        5000          1
                   SALESMAN         4000          3
                                           52125         12  => 요 부분은 두 번째 ROLLUP을 이용해서 구했습니다.
 


CUBE Operator를 사용하면 편하게 하나의 SQL문으로 위의 결과를 얻을 수 있습니다.
직접 SQL문을 실행시켜 보면 쉽게 이해가 갑니다.


SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_count
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY CUBE(b.dname, a.job)

DNAME      JOB               SAL  EMP_COUNT
---------- ---------- ---------- ----------
ACCOUNTING CLERK               1300          1
ACCOUNTING MANAGER          2450          1
ACCOUNTING PRESIDENT        5000          1
ACCOUNTING                         8750          3 =>ACCOUNTING 부서의 직업별 급여의 총계와 사원수.
RESEARCH    ANALYST           6000          2
RESEARCH    CLERK               1900          2
RESEARCH    MANAGER          2975          1
RESEARCH                           10875          5=>RESEARCH 부서의 직업별 급여의 총계와 사원수.
SALES          MANAGER         28500          1
SALES          SALESMAN         4000          3
SALES                                 32500          4=>SALES 부서의 직업별 급여 총계와 사원수.
                   ANALYST          6000          2
                   CLERK              3200          3
                   MANAGER         33925          3
                   PRESIDENT        5000          1
                   SALESMAN         4000          3   
                                           52125         12  => 직업별로 급여의  총계와 사원수를 보여줍니다.


CUBE를 어느 경우에 사용 할 수 있는지 이해 되셨죠..
CUBE Operator는 Cross-Tab에 대한 Summary를 추출하는데 사용 됩니다
즉 ROLLUP에 의해 나타내어지는 Item Total값과 Column Total값을 나타 낼 수 있습니다.

너무 어렵게 설명했나요... 응용해서 테스트 해보세요..


◈ GROUPING() 함수


GROUPING Function은 ROLLUP, CUBE Operator에 모두 사용할 수 있습니다.

GROUPING Function는 해당 Row가 GROUP BY에 의해서 산출된 Row인 경우에는 0을 반환하고,
ROLLUP이나 CUBE에 의해서 산출된 Row인 경우에는 1을 반환하게 됩니다.

따라서 해당 Row가 결과집합에 의해 산출된 Data인지,
ROLLUP이나 CUBE에 의해서 산출된 Data인지를 알 수 있도록 지원하는 함수입니다.


SELECT b.dname, a.job, SUM(a.sal) sal, COUNT(a.empno) emp_count,
       GROUPING(b.dname) "D", GROUPING(a.job) "S"
FROM emp a, dept b
WHERE a.deptno = b.deptno
GROUP BY CUBE(b.dname, a.job)


DNAME        JOB               SAL  EMP_COUNT    D    S
----------   ----------    ------- ---------- ---- ----
ACCOUNTING CLERK            1300          1    0    0
ACCOUNTING MANAGER       2450          1    0    0
ACCOUNTING PRESIDENT     5000          1    0    0
ACCOUNTING                      8750          3    0    1
RESEARCH    ANALYST        6000          2    0    0
RESEARCH    CLERK            1900          2    0    0
RESEARCH    MANAGER       2975          1    0    0
RESEARCH                        10875          5    0    1
SALES          MANAGER      28500          1    0    0
SALES          SALESMAN      4000          3    0    0
SALES                              32500          4    0    1
                   ANALYST         6000          2    1    0
                   CLERK             3200          3    1    0
                   MANAGER      33925          3    1    0
                   PRESIDENT     5000          1    1    0
                   SALESMAN      4000          3    1    0
                                       52125         12    1    1
 


신고
Posted by naearu

http://blog.naver.com/tomatogun/100040675312

MySQL:
SELECT column FROM table ORDER BY RAND() LIMIT 1


PostgreSQL:
SELECT column FROM table ORDER BY RANDOM() LIMIT 1


Microsoft SQL Server:
SELECT TOP 1 column FROM table ORDER BY NEWID()


IBM DB2:
SELECT column FROM table ORDER BY RAND() FETCH FIRST 1 ROWS ONLY


Oracle:
SELECT column FROM ( SELECT column FROM table ORDER BY dbms_random.value ) WHERE rownum = 1


DBMS마다 다 다르니 ;;

알아두자

신고
Posted by naearu

<?

if(!$pidx) $pidx=0;
$i=0;
if($pidx!=0){
 while(1){
 
 $query="select * from radar.PROJECT where P_IDX=".$pidx."";
 
 $res  = mysql_query($query, $Conn) or
            die('SQL:-1 ' . $query . '<br> ㅁㄴㅇ<br>' . mysql_errno() . ': ' . mysql_error());
 
 $btData = mysql_fetch_array($res);
 $stack[$i]['P_PARENT']=$btData['P_PARENT'];
 $stack[$i]['P_NAME']=$btData['P_NAME'];
 $stack[$i]['P_IDX']=$btData['P_IDX'];
 $pidx=$btData['P_PARENT'];
 if(!$btData['P_PARENT']) break;
 $i++;
 }
 
 //print_r($stack);
 //echo $i;
 
}


?>

  <!-- 프로젝트 선택 시작 -->

<?
  echo "<a href=channel.php?pidx=0>ROOT</a>  >  ";
 for($i;$stack[$i];$i--){
 
  echo "<a href='channel.php?pidx=".$stack[$i]['P_IDX']."'>[".$stack[$i]['P_NAME']."]</a>  >  ";
 //echo $stack[$i]['P_IDX'].",";
 //echo $stack[$i]['P_PARENT'].",";
 //echo $stack[$i]['P_NAME'].",";
 $pidx=$stack[$i]['P_IDX'];
 
 $select_name=$stack[$i]['P_NAME'];
}

     
     
      $query="select count(*) from radar.PROJECT where P_PARENT=".$pidx;
       $res  = mysql_query($query, $Conn) or
           die('SQL:0: ' . $query . '<br> ㅁㄴㅇ<br>' . mysql_errno() . ': ' . mysql_error());
       $btData = mysql_fetch_array($res);
       
?>      

<? if($btData[0]>0){ ?>
       <select name="1" onchange="window.open(value,'_self');" size=1>
      <option >선택하세요.</option>
       <?
       $query="select * from radar.PROJECT where P_PARENT=".$pidx;
       $res  = mysql_query($query, $Conn) or
           die('SQL:0: ' . $query . '<br> ㅁㄴㅇ<br>' . mysql_errno() . ': ' . mysql_error());
       for($i=1;$btData = mysql_fetch_array($res);$i++)
       {
       ?>
        <option value="channel.php?pidx=<?=$btData[P_IDX]?>" <?=selected($btData[P_IDX],$pidx)?>>[<?=$btData[P_NAME]?>]</option>
       <?}?>
     </select>
<? } ?>


스텍같은 기능으로 마지막에 넣은게 첨나오게...


 중간부터 시작해서  4>3>2>1>0 이렇게 집어 넣고

0>1>2>3>4 이렇게 빼서...

4아래에 또 뭐 있나 검사하면 끝!

아..생각보다 간단한건데.. ㅠㅠ 켕..

신고
Posted by naearu

INNER JOIN (교집합)

 

INNER JOIN(NORMAL JOIN)은 여러 테이블의 조건들이 모두 만족했을때만 데이타를 보여주게 되며 한쪽 테이블의 조건이라도 만족하지 않으면 데이타를
보여주지 않습니다.

 

LEFT OUTER JOIN (교집합)

 

LEFT OUTER JOIN(교집합)은 여러 테이블의 조건들이 모두 만족하지 않더라도 데이타를 보여줍니다.

 

※ 조건이 만족하지 않는 테이블의 데이타값은 "NULL" 값으로 출력된다.

 

간단한 조인 예제

 

개요


출석 테이블을 만든다 가정하면 normal join 으로는, 한번도 출석하지 않은 학생은 목록에도 보이지 않게 되지만, outer join 으로는 모두 볼 수 있게 됩니다.


예제


[테이블 생성]


drop table book;
create table book
(
code varchar(10),
name varchar(10)
);
insert into book values ('1111','사랑책');
insert into book values ('2222','이별책');
insert into book values ('3333','웃긴책');


drop table animal;

create table animal
(
code varchar(10),
name varchar(10)
);
insert into animal values ('1111','사자');
insert into animal values ('2222','호랑이');
insert into animal values ('3333','오리');


drop table buy;
create table buy
(
book_code varchar(10),
animal_code varchar(10)
);
insert into buy values ('1111','1111');
insert into buy values ('2222','2222');
insert into buy values ('3333','4444');


[LEFT OUTER JOIN 예제]


select
 b.name, c.name
from
 buy as a
 left outer join book as b on a.book_code = b.code
 left outer join animal as c on a.animal_code = c.code;


※ left outer join 시에는 최대한 중복건이 안나오도록 유일한 컬럼으로 비교해야 한다.

※ left outer join 시에 조건에 만족하지 않는 테이블의 컬럼값은 "NULL" 로 표기된다.


[INNER JOIN 방법1]


select
 b.name, c.name
from
 buy as a
 inner join book as b on a.book_code = b.code
 inner join animal as c on a.animal_code = c.code;


[INNER JOIN 방법2]


select
 b.name, c.name
from
 buy as a, book as b, animal as c
where
 a.book_code = b.code and a.animal_code = c.code where a.code = '1111';

select
 b.name, c.name
from
 buy as a, book as b, animal as c where a.book_code = '1111';


여러 테이블 컬럼의 모든 경우의 수를 출력한다.


select * from book, animal, buy;

select * from book a, animal b, buy c;


-- 3개테이블 컬럼의 경우의 수를 모두 출력한다.

-- 모든 경우의 수 = 각테이블의 로우스를 곱한값


신고
Posted by naearu
 

용문

ls_1의 값을 id 번호를 받아서 순위를 나타냄.


mysql> select (select count(*) from std_point where ls_1>=sp.ls_1) as rank,sp.ls_1,sp.id from std_point sp where id=3;

+------+------+----+
| rank | ls_1 | id |
+------+------+----+
|   3  |   54 |  3 |
+------+------+----+
1 row in set (0.00 sec)

대략 10만건정도 해서 돌려봣더니 하나뽑는데 0.08초 정도 걸리더라는 ㄱ-;;

신고
Posted by naearu

std_data

+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(10) | NO   |     | 0       |                |
| class | varchar(10) | NO   |     | 0       |                |
| add   | varchar(10) | NO   |     | 0       |                |
+-------+-------------+------+-----+---------+----------------+

std_point

+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id    | int(11)      | NO   | PRI |         |       |
| level | tinyint(10)  | NO   |     |         |       |
| ls_1  | tinyint(100) | NO   |     |         |       |
| ls_2  | tinyint(100) | NO   |     |         |       |
| ls_3  | tinyint(100) | NO   |     |         |       |
+-------+--------------+------+-----+---------+-------+

ysql> select * from std_point;
----+-------+------+------+------+
 id | level | ls_1 | ls_2 | ls_3 |
----+-------+------+------+------+
  1 |     1 |   98 |   23 |   88 |
  2 |     3 |   10 |   63 |   88 |
  3 |     2 |   54 |   27 |   56 |
  4 |     3 |   38 |    3 |   76 |
  5 |     3 |   22 |   95 |   80 |
  6 |     2 |   14 |   59 |   88 |
  7 |     1 |   74 |   35 |  100 |
  8 |     1 |   46 |   43 |  100 |
  9 |     2 |   22 |   55 |   56 |
 10 |     1 |   10 |   27 |   88 |
----+-------+------+------+------+


mysql> select * from std_data;
+----+------+-------+---------+
| id | name | class | add     |
+----+------+-------+---------+
|  1 | 2    | 1-2   | 102-167 |
|  2 | 2    | 1-1   | 146-107 |
|  3 | 3    | 1-1   | 178-155 |
|  4 | 1    | 1-2   | 186-127 |
|  5 | 2    | 1-1   | 110-123 |
|  6 | 2    | 1-1   | 170-195 |
|  7 | 3    | 1-3   | 106-179 |
|  8 | 1    | 1-3   | 138-123 |
|  9 | 3    | 1-2   | 174-131 |
| 10 | 1    | 1-1   | 166-151 |
+----+------+-------+---------+

 

테이블 별명 단축..
select * from std_data
이러한 쿼리를
select * from std_data sd

라고 선언할수 있다.

그러므로써 뒤의 where문 뒤의 조건식에서
select * from std_data sd where sd.id<5
와 같은식으로 표기할수 있어진다.

그리고 앞쪽의 필드 구분에서도 이용가능하다.

 

◆◆ The Cross Join

mysql> select * from std_data,std_point;
+----+------+-------+---------+----+-------+------+------+------+
| id | name | class | add     | id | level | ls_1 | ls_2 | ls_3 |
+----+------+-------+---------+----+-------+------+------+------+
|  1 | 2    | 1-2   | 102-167 |  1 |     1 |   98 |   23 |   88 |
|  2 | 2    | 1-1   | 146-107 |  1 |     1 |   98 |   23 |   88 |
|  3 | 3    | 1-1   | 178-155 |  1 |     1 |   98 |   23 |   88 |
|  4 | 1    | 1-2   | 186-127 |  1 |     1 |   98 |   23 |   88 |
.
.
.
.

100 rows in set (0.00 sec)


한 데이터당 한데이터씩 매치시켜가며 표기한다.
10x10 즉 100개의 결과를 내놓는다.

 

 


mysql> select sd.add,sp.id from std_data sd,std_point sp where sp.id='5';
+---------+----+
| add     | id |
+---------+----+
| 102-167 |  5 |
| 146-107 |  5 |
| 178-155 |  5 |
| 186-127 |  5 |
| 110-123 |  5 |
| 170-195 |  5 |
| 106-179 |  5 |
| 138-123 |  5 |
| 174-131 |  5 |
| 166-151 |  5 |
+---------+----+
10 rows in set (0.02 sec)

id를 add에 한번씩 매치시켜 표시한다.
1x10 즉 10개의 결과를 내놓는다.

 


◆◆ The Equi-join
직접 테이블의 필드와 필드를 비교해서 값을 가져온다.

mysql> select sd.add,sp.id from std_data sd,std_point sp where sp.id=sd.id and sd.id=3;
+---------+----+
| add     | id |
+---------+----+
| 178-155 |  3 |
+---------+----+
1 row in set (0.30 sec)

필드의 값을 직접비교해서 결과를 가져온다.

 


◆◆ The Left Join

mysql> select * from std_data left join std_point on std_data.id=std_point.id;
+----+------+-------+---------+------+-------+------+------+------+
| id | name | class | add     | id   | level | ls_1 | ls_2 | ls_3 |
+----+------+-------+---------+------+-------+------+------+------+
|  1 | 2    | 1-2   | 102-167 |    1 |     1 |   98 |   23 |   88 |
|  2 | 2    | 1-1   | 146-107 |    2 |     3 |   10 |   63 |   88 |
|  3 | 3    | 1-1   | 178-155 |    3 |     2 |   54 |   27 |   56 |
|  4 | 1    | 1-2   | 186-127 |    4 |     3 |   38 |    3 |   76 |
|  5 | 2    | 1-1   | 110-123 |    5 |     3 |   22 |   95 |   80 |
|  6 | 2    | 1-1   | 170-195 |    6 |     2 |   14 |   59 |   88 |
|  7 | 3    | 1-3   | 106-179 |    7 |     1 |   74 |   35 |  100 |
|  8 | 1    | 1-3   | 138-123 |    8 |     1 |   46 |   43 |  100 |
|  9 | 3    | 1-2   | 174-131 |    9 |     2 |   22 |   55 |   56 |
| 10 | 1    | 1-1   | 166-151 |   10 |     1 |   10 |   27 |   88 |
+----+------+-------+---------+------+-------+------+------+------+
10 rows in set (0.00 sec)

두 테이블을 합쳐서 한화면에 보여준다.
요구한 필드의 값이 같은것들을 찾아서 보여준다.

Left Join이 아니더라도
mysql> select * from std_data , std_point where std_data.id=std_point.id;
이런 쿼리를 보내면 같은 결과를 얻을수 있다.


◆ The Using Clause
조금더 편리한 방법으로 using 을 사용해서 아래와 같은 결과를 얻을수 잇다.
겹쳐지는 id 부분은 한번만 출력한다.
mysql> select * from std_data left join std_point using(id);
+----+------+-------+---------+-------+------+------+------+
| id | name | class | add     | level | ls_1 | ls_2 | ls_3 |
+----+------+-------+---------+-------+------+------+------+
|  1 | 2    | 1-2   | 102-167 |     1 |   98 |   23 |   88 |
|  2 | 2    | 1-1   | 146-107 |     3 |   10 |   63 |   88 |
|  3 | 3    | 1-1   | 178-155 |     2 |   54 |   27 |   56 |
|  4 | 1    | 1-2   | 186-127 |     3 |   38 |    3 |   76 |
|  5 | 2    | 1-1   | 110-123 |     3 |   22 |   95 |   80 |
|  6 | 2    | 1-1   | 170-195 |     2 |   14 |   59 |   88 |
|  7 | 3    | 1-3   | 106-179 |     1 |   74 |   35 |  100 |
|  8 | 1    | 1-3   | 138-123 |     1 |   46 |   43 |  100 |
|  9 | 3    | 1-2   | 174-131 |     2 |   22 |   55 |   56 |
| 10 | 1    | 1-1   | 166-151 |     1 |   10 |   27 |   88 |
+----+------+-------+---------+-------+------+------+------+
10 rows in set (0.00 sec)

 

 

 


◆◆ Self-joins

mysql> select * from std_data as sd1, std_data as sd2;
+----+------+-------+---------+----+------+-------+---------+
| id | name | class | add     | id | name | class | add     |
+----+------+-------+---------+----+------+-------+---------+
|  1 | 2    | 1-2   | 102-167 |  1 | 2    | 1-2   | 102-167 |
|  2 | 2    | 1-1   | 146-107 |  1 | 2    | 1-2   | 102-167 |
|  3 | 3    | 1-1   | 178-155 |  1 | 2    | 1-2   | 102-167 |
|  4 | 1    | 1-2   | 186-127 |  1 | 2    | 1-2   | 102-167 |

처음에 했던 크로스 조인과 비슷한 출력물을 내놓는다.


 

신고
Posted by naearu
사칙연산

- 예 : select (((3 + 2) * 4) / (2 - 1));
- 주의 : 0 으로 나눌경우 NULL 반환한다. 연산은 BIGINT 의 결과값을 가지게 되므로 BIGINT 의 범위를 벗어나게 되면 잘못된 값을 반환한다.

비트연산

- | : 비트연산 OR 의 연산자이다.
- 예 : select 29 | 15;

- & : 비트연산 AND 의 연산자이다.
- 예 : select 29 & 15;

- << : 비트연산 OR 의 연산자이다.
- 예 : select 1 << 2;

- >> : 비트연산 OR 의 연산자이다.
- 예 : select 4 >> 2;

- BIT_COUNT(N) : 해당 값의 비트수를 반환한다.
- 예 : select BIT_COUNT(29);

- 주의 : 연산은 BIGINT 의 결과값을 가지게 되므로 BIGINT 의 범위를 벗어나게 되면 잘못된 값을 반환한다.

논리연산

- 주의 : 모든 논리연산은 1(TRUE) 또는 0(FALSE) 을 반환한다. 논리연산자는 우선순위가 높기 때문에 순서에 조심해야한다.
- 예 : select ! 1+1; 이 문장은 select (! 1) + 1; 으로 연산된다.

- ! : 논리연산 NOT 의 연산자이다. 0 이외의 모든 값은 TRUE 의 의미이다. 따라서 NOT 0 만이 1을 반환한다. 예외적으로 NOT NULL 은 NULL 을 반환한다.
- 예 : select ! (100);
select ! (1+1);
select ! 1+1;

- || : 논리연산 OR 의 연산자이다. 두개의 인자가 모두 0 또는 NULL 일 경우만 0 을 반환하고, 이외에는 1을 반환한다.
- 예 : select 1 || 0;
select 0 || 0;
select 100 || NULL;

- && : 논리연산 AND 의 연산자이다. 두개의 인자중 하나라도 0 또는 NULL 이 있을 경우 0 을 반환한다.
- 예 : select 1 && NULL;
신고
Posted by naearu
비교연산

- 비교연산의 결과값은 1(TRUE), 0(FALSE), 또는 NULL 을 반환한다. 비교연산은 숫자와 문자열 모두에서 가능하다. 필요에 따라 자동적으로 숫자로 또는 문자열로 변환된다.
- 두개의 인자 모두가 NULL 일 경우 연산의 결과값은 NULL 이 된다.
- 두개의 인자 모두가 문자열이면 문자열로 비교된다.
- 두개의 인자 모두가 숫자이면 숫자로서 비교된다.
- 16진수는 숫자와 연산하지 않을 경우 바이너리로 처리된다.
- 다른 대부분의 경우 연산은 floating-point 로 된다.
- 기본적으로, 문자열 비교는 대소문자구분을 하지 않는다.
예 : select * from tbl_a where (a > 0) and (b <= 1);


- expr BETWEEN min AND max
- 예 : select 2 BETWEEN 2 AND '3';


- expr IN (value,...)
- 예 : select 'wefwf' IN (0,3,5,'wefwf');


- expr NOT IN (value,...)


- ISNULL(expr) : NULL 일 경우만 1(TRUE) 를 반환한다.
- 예 : select ISNULL(1+1);


- COALESCE(list) : NULL 이 아닌 첫번째 인자를 반환한다.
- 예 : select COALESCE(2, ',한글', NULL, 1);


- expr [NOT] REGEXP pat : 쿼리에서 정규표현식을 사용할수 있다. 사용할수 있다. 이것에 대해서는 나중에 설명한다.


- expr RLIKE pat : REGEXP 와 같다.


- STRCMP(expr1,expr2) : 두개의 문자열이 동일할경우 0, 첫번째 문자열이 정렬에서 상위일경우 -1, 그렇지 않으면 1을 반환한다.


= 같다 값 = 4
> 보다크다 값 > 60
< 보다작다 값 < 60
>= 크거나 같다 값 >= 60
<= 작거나 같다 값 <= 60
!= 혹은 <> 같지 않다 값 != 0
IS NOT NULL NULL을 가지지 않는다.
IS NULL NULL 이다.
BETWEEN 0에서 60 사이의 값
IN 어느 집합에 있는가
NOT IN 어느 집합에 있지 않은가
NOT IN LIKE 패턴대응 name like("값%")
NOT LIKE 패턴대응 name not like("값%")
REGEXP 정규표현 name regexp
신고
Posted by naearu
형변환 연산자

- BINARY : 일반적인 문자열은 대소문자를 구분하지 않고 조건을 검색하지만 BINARY 를 사용할 이진연산을 하기때문에 대소문자 검색을 해야할 경우 편리하다.
- 예 : select BINARY "a" = "A";



컨트롤 함수

- IFNULL(expr1,expr2) : expr1 이 NULL 이 아니면 expr1 을 반환하고 그렇지 않을 경우 expr2 를 반환한다. 문자열, 숫자 모두 사용가능하다.
- 예 : select IFNULL(1/0,10);

- IF(expr1,expr2,expr3) : 만약 expr1 이 1(TRUE) 이면 expr2 를, 그렇지 않으면 expr3 을 반환한다.
- 예 : select IF(1>2,2,3);
select IF(strcmp('test','test1'),'yes','no');

- CASE value WHEN [compare-value] THEN result [WHEN [compare-value] THEN result ...] [ELSE result] END
- 예 : SELECT CASE 1 WHEN 1 THEN "one" WHEN 2 THEN "two" ELSE "more" END;
SELECT CASE WHEN 1>0 THEN "true" ELSE "false" END;
SELECT CASE BINARY "B" when "a" then 1 when "b" then 2 END;
신고
Posted by naearu
- ABS(X) : 절대값을 반환한다. 음수에 대해서는 양수를 반환한다.
- 예 : select ABS(-32);

- SIGN(X) : 양음수인지를 반환한다. 즉 SIGN(-32) 는 -1, SIGN(0) 은 0, SIGN(234) 은 1 을 반환한다.
- 예 : select SIGN(-32);

- MOD(N,M) : 나머지 값을 반환한다.
- 예 : select MOD(29,9);

- FLOOR(X) : 해당 인자의 값을 넘지 않는 최대 정수값을 반환한다. 예를 들어, select FLOOR(-1.23) 는 -2 를 반환한다.
- 예 : select FLOOR(1.23);

- CEILING(X) : 해당 인자보다 작지 않은 최소정수를 반환한다. 예를 들어, select CEILING(-1.23) 은 -1 을 반환한다.

- ROUND(X) : 해당 인자에 대해 반올림 한 값을 넘긴다. 예를 들어, select ROUND(-1.58) 에 대해서는 -2 를 반환한다.
- 예 : select ROUND(1.58);

- ROUND(X,D) : 두번째 인자의 소수점 자리수만큼 반올림한다. 예를 들어, select ROUND(1.298, 1) 는 1.3 을 반환한다.

- POW(X,Y) : X 의 Y 제곱의 값을 반환한다.
- 예 : select POW(2,3);

- POWER(X,Y) : POW(X,Y) 와 동일하다.

- PI() : 파이값을 반환한다.

- LEAST(X,Y,...) : 해당 인자들중 최소값을 반환한다.
- 예 : select LEAST(34.0,3.0,5.0,767.0);

- GREATEST(X,Y,...) : 해당 인자들중 최대값을 반환한다.
- 예 : select GREATEST("B","A","C");

- TRUNCATE(X,D) : 두번째 자리수 많큼의 값을 반환한다. 반올림은 하지 않는다.
- 예 : select TRUNCATE(1.999,0);
신고
Posted by naearu
- COUNT(expr) : GROUP BY 로 묶인 부분에 대한 합계를 반환한다.
- 예 : select student.student_name,COUNT(*)
from student,course
where student.student_id=course.student_id
GROUP BY student_name;
- 참고 : 한개의 테이블에 대해, WHERE 절이 없는 경우 COUNT(*) 가 최적화 되어 있어 매우 빠르다.
- 예 : select COUNT(*) from student;

- AVG(expr) : GROUP BY 로 묶인 부분에 대한 평균값을 반환한다.
- 예 : select student_name, AVG(test_score)
from student
GROUP BY student_name;

- MIN(expr) : GROUP BY 로 묶인 부분에서 최소값을 반환한다.
- MAX(expr) : GROUP BY 로 묶인 부분에서 최대값을 반환한다.
- 예 : select student_name, MIN(test_score), MAX(test_score)
from student
GROUP BY student_name;
- 참고 : expr 에는 문자열이 들어갈수 있으며, 그럴경우 문자열 길이의 최소/최대인 값을 반환한다.

- SUM(expr) : GROUP BY 로 묶인 부분에 대한 합계를 반환한다.
- 주의 : 해당하는 row 가 하나도 없을경우 NULL 을 반환한다.
신고
Posted by naearu
- DAYOFWEEK(date) : 해당 날짜의 요일을 숫자로 반환한다. 일요일은 1, 토요일은 7 이다.
- 예 : select DAYOFWEEK('1998-02-03');

- WEEKDAY(date) : 해당 날짜에 대한 요일을 반환한다. 월요일은 0, 일요일은 6 이다.
- 예 : select WEEKDAY('1997-10-04 22:23:00');

- DAYOFYEAR(date) : 해당 날짜의 1월 1일부터의 날수를 반환한다. 결과값은 1에서 366 까지이다.
- 예 : select DAYOFYEAR('1998-02-03');

- YEAR(date) : 해당 날짜의 년을 반환한다.
- 예 : select YEAR('98-02-03');

- MONTH(date) : 해당 날짜의 월을 반환한다.
- 예 : select MONTH('1998-02-03');

- DAYOFMONTH(date) : 해당 날짜의 일을 반환한다. 결과값은 1 에서 31 까지이다.
- 예 : select DAYOFMONTH('1998-02-03');

- HOUR(time) : 해당날짜의 시간을 반환한다. 결과값은 0 에서 23 이다.
- 예 : select HOUR('10:05:03');

- MINUTE(time) : 해당날짜의 분을 반환한다. 결과값은 0 에서 59 이다.
- 예 : select MINUTE('98-02-03 10:05:03');

- SECOND(time) : 해당날짜의 초를 반환한다. 결과값은 0 에서 59 이다.
- 예 : select SECOND('10:05:03');

- DAYNAME(date) : 해당 날짜의 요일 이름을 반환한다. 일요일은 'Sunday' 이다.
- 예 : select DAYNAME("1998-02-05");

- MONTHNAME(date) : 해당 날짜의 월 이름을 반환한다. 2월은 'February' 이다.
- 예 : select MONTHNAME("1998-02-05");

- QUARTER(date) : 해당 날짜의 분기를 반환한다. 결과값은 1 에서 4 이다.

- WEEK(date,first) : 1월 1일부터 해당날가지의 주 수를 반환한다. 주의 시작을 일요일부터 할경우는 두번째 인자를 0, 월요일부터 시작할 경우는 1 을 넣는다. 결과값은 1 에서 52 이다.
- 예 : select WEEK('1998-02-20',1);

- PERIOD_ADD(P,N) : P (형식은 YYMM 또는 YYYYMM 이어야 한다.) 에 N 만큼의 달 수를 더한값을 반환한다. 주의할것은 두번째 인자는 숫자라는 것이다.
- 예 : select PERIOD_ADD(9801,2);

- PERIOD_DIFF(P1,P2) : 두개의 인자 사이의 달 수를 반환한다. 두개의 인자 모두 형식은 YYMM 또는 YYYYMM 이어야 한다.

- DATE_ADD(date,INTERVAL expr type) : 날짜를 더한 날짜를 반환한다.
- DATE_SUB(date,INTERVAL expr type) : 날짜를 뺀 날짜를 반환한다.
- ADDDATE(date,INTERVAL expr type) : DATE_ADD(date,INTERVAL expr type) 와 동일하다.
- SUBDATE(date,INTERVAL expr type) : DATE_SUB(date,INTERVAL expr type) 와 동일하다.
- EXTRACT(type FROM date) : 날짜에서 해당 부분을 추출한다.
- 예 : SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 SECOND);
SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL 1 DAY);
SELECT DATE_ADD("1997-12-31 23:59:59", INTERVAL "1:1" MINUTE_SECOND);
SELECT DATE_SUB("1998-01-01 00:00:00", INTERVAL "1 1:1:1" DAY_SECOND);
SELECT DATE_ADD("1998-01-01 00:00:00", INTERVAL "-1 10" DAY_HOUR);
SELECT DATE_SUB("1998-01-02", INTERVAL 31 DAY);
SELECT EXTRACT(YEAR FROM "1999-07-02");
SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
- 참고 : type 에 사용되는 키워드는 SECOND, MINUTE, HOUR, DAY, MONTH, YEAR, MINUTE_SECOND, HOUR_MINUTE, DAY_HOUR, YEAR_MONTH, HOUR_SECOND, DAY_MINUTE, DAY_SECOND 이다.
- 주의 : 계산한 달의 날수가 작을 경우는 해당달의 마지막 날을 반환한다. 예를 들어 select DATE_ADD('1998-01-30', Interval 1 month); 의 경우 1998-02-28 을 반환한다.

- TO_DAYS(date) : 0 년 부터의 날짜수를 반환한다. 이 함수는 1582 이전 날에 대해서는 계산하지 않는다.
- 예 : select TO_DAYS(950501);

- FROM_DAYS(N) : 해당 숫자만큼의 날짜를 반환한다. 이 함수는 1582 이전 날에 대해서는 계산하지 않는다.
- 예 : select FROM_DAYS(729669);

- DATE_FORMAT(date,format) : 날짜를 해당 형식의 문자열로 변환하여 반환한다.
- 예 : select DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');
select DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
select DATE_FORMAT('1997-10-04 22:23:00', '%D %y %a %d %m %b %j');
select DATE_FORMAT('1997-10-04 22:23:00', '%H %k %I %r %T %S %w');
- 참고 : 형식은 다음과 같다. %M (달 이름), %W (요일 이름), %Y (YYYY 형식의 년도), %y (YY 형식의 년도), %a (요일 이름의 약자), %d (DD 형식의 날짜), %e (D 형식의 날짜), %m (MM 형식의 날짜), %c (M 형식의 날짜), %H (HH 형식의 시간, 24시간 형식), %k (H 형식의 시간, 24시간 형식), %h (HH 형식의 시간, 12시간 형식), %i (MM 형식의 분), %p (AM 또는 PM)

- TIME_FORMAT(time,format) : DATE_FORMAT(date,format) 과 같은 방식으로 사용할수 있으나 날 이상의 것에 대해서는 NULL 이나 0 을 반환한다.

- CURDATE() : 현재날짜를 반환한다. 숫자와 연산을 할경우 숫자로 변환된다. 형식은 'YYYY-MM-DD' 또는 YYYYMMDD 이다.
- 예 : select CURDATE();
select CURDATE() + 0;

- CURTIME() : 현재시간을 반환한다. 숫자와 연산을 할경우 숫자로 변환된다. 형식은 'HH:MM:SS' 또는 HHMMSS 이다.
- 예 : select CURTIME();
select CURTIME() + 0;

- SYSDATE() : 현재날짜시간을 반환한다. 숫자와 연산을 할경우 숫자로 변환된다. 형식은 'YYYY-MM-DD HH:MM:SS' 또는 YYYYMMDDHHMMSS 이다.
- 예 : select NOW();
select NOW() + 0;

- NOW() : SYSDATE() 와 동일하다.

- UNIX_TIMESTAMP() : '1970-01-01 00:00:00' 부터의 초를 반환한다. 인자가 주어질 경우는 해당 날짜에 대한 유닉스 시간을 반환한다.
- 예 : select UNIX_TIMESTAMP();
select UNIX_TIMESTAMP('1997-10-04 22:23:00');

- FROM_UNIXTIME(unix_timestamp) : 유닉스시간에서 날짜 형식으로 변환한다.
- 예 : select FROM_UNIXTIME(875996580);

- FROM_UNIXTIME(unix_timestamp,format) : 유닉스시간을 날짜형식으로 변환하고 DATE_FORMAT(date,format) 에서 설명한 포맷으로 변환하여 반환한다.
- 예 : select FROM_UNIXTIME(UNIX_TIMESTAMP(), '%Y %D %M %h:%i:%s %x');

- TIME_TO_SEC(time) : 해당 시간의 0:0:0 에서부터의 초를 반환한다.
- 예 : select TIME_TO_SEC('22:23:00');

- SEC_TO_TIME(seconds) : 초를 시간으로 바꾼다.
- 예 : select SEC_TO_TIME(2378);
신고
Posted by naearu


- ASCII(str) : 해당 인저의 아스키 값을 반환한다. 문자열이 한글자 이상일 경우는 첫번째 문자에 해당하는 아스키 값을 반환한다. 빈 문자열에 대해서는 0, NULL 에 대해서는 NULL 을 반환한다.
- 예 : select ASCII('2');

- CONCAT(X,Y,...) : 해당 인자들을 연결한 문자열을 반환한다. 인자중 하나가 NULL 일 경우는 NULL 을 반환한다.
- 예 : select CONCAT('My', 'S', 'QL');

- LENGTH(str) : 문자열의 길이를 반환한다.
- 예 : select LENGTH('text');

- OCTET_LENGTH(str) : LENGTH(str) 와 동일하다.

- CHARACTER_LENGTH(str) : LENGTH(str) 와 동일하다.

- LOCATE(substr,str) : 첫번째 인자에서 두번째 인자가 있는 위치를 반환한다. 없을경우 0 을 반환한다.
- 예 : select LOCATE('bar', 'foobarbar');

- POSITION(substr IN str) : LOCATE(substr,str) 와 동일하다.

- LOCATE(substr,str,pos) : 두번째 인자에서 세번째 인자의 자리수부터 검색을 하여 첫번째 인자가 발견되는 위치를 반환한다.
- 예 : select LOCATE('bar', 'foobarbar',5);

- INSTR(str,substr) : LOCATE(substr,str) 와 동일한 기능을 하며, 차이점은 첫번째 인자와 두번째 인자가 바뀐것 뿐이다.
- 예 : select INSTR('foobarbar', 'bar');

- LPAD(str,len,padstr) : 첫번째 인자를 두번째 인자만큼의 길이로 변환한 문자열을 반환한다. 모자란 공간은 왼쪽에 세번째 인자로 채운다.
- 예 : select LPAD('hi',4,' ');

- RPAD(str,len,padstr) : LPAD 와 반대로 오른쪽에 빈공간을 채운다.
- 예 : select RPAD('hi',5,'?');

- LEFT(str,len) : 첫번째 문자열에서 두번째 길이만큼만을 반환한다.
- 예 : select LEFT('foobarbar', 5);

- RIGHT(str,len) : LEFT(str,len) 와 동일하다. 차이점은 해당 길이만큼 오른쪽에서부터 반환한다.
- 예 : select RIGHT('foobarbar', 4);
select SUBSTRING('foobarbar' FROM 4);

- SUBSTRING(str,pos,len) : 첫번째 인자의 문자열에서 두번째 인자의 위치부터 세번째 인자의 길이만큼 반환한다.
- 예 : select SUBSTRING('Quadratically',5,6);

- SUBSTRING(str FROM pos FOR len) : SUBSTRING(str,pos,len) 과 동일하다.

- MID(str,pos,len) : SUBSTRING(str,pos,len) 과 동일하다.

- SUBSTRING(str,pos) : 첫번째 인자의 문자열에서 두번째 인자로부터의 모든 문자열을 반환한다.
- 예 : select SUBSTRING('Quadratically',5);

- SUBSTRING(str FROM pos) : SUBSTRING(str,pos) 와 동일하다.

- SUBSTRING_INDEX(str,delim,count) : 첫번째 인자인 문자열을 두번째 문자로 구분하여 세번째 인자 수의 위치만큼 반환한다. 예를들어 select SUBSTRING_INDEX('www.mysql.com', '.', 2) 은 'www.mysql' 을 반환한다. 세번째 인자가 음수일경우는 반대로 오른쪽에서부터 검색하여 결과를 반환한다.
- 예 : select SUBSTRING_INDEX('www.mysql.com', '.', -2);

- LTRIM(str) : 왼쪽에 있는 공백문자를 제거한 문자열을 반환한다.
- 예 : select LTRIM(' barbar');

- RTRIM(str) : 오른쪽에 있는 공백문자를 제거한 문자열을 반환한다.
- 예 : select RTRIM('barbar ');

- TRIM([[BOTH | LEADING | TRAILING] [remstr] FROM] str)
- 예 : select TRIM(' bar ');
select TRIM(LEADING 'x' FROM 'xxxbarxxx');
select TRIM(BOTH 'x' FROM 'xxxbarxxx');
select TRIM(TRAILING 'xyz' FROM 'barxxyz');

- REPLACE(str,from_str,to_str) : 문자열은 치환한다.
- 예 : select REPLACE('www.mysql.com', 'www', 'ftp');

- REVERSE(str) : 문자열을 뒤집는다. 예를들어, select REVERSE('abc') 은 'cba' 를 반환한다.

- LCASE(str) : 문자열을 소문자로 변환한다.
- 예 : select LCASE('QUADRATICALLY');

- LOWER(str) : LCASE(str) 와 동일하다.

- UCASE(str) : 문자열을 대문자로 변환한다.
- 예 : select UCASE('Hej');

- UPPER(str) : UCASE(str) 와 동일하다.
신고
Posted by naearu
TAG MySQL, 함수

MVC (model-view-controller)

객체지향프로그래밍에서, MVC란 사용자 인터페이스를 성공적이며 효과적으로 데이터 모형에 관련 시키기 위한 방법론 또는 설계 방식중 하나이다. MVC 방식은 자바, Smalltalk, C 및 C++ 등과 같은 프로그래밍 언어를 쓰는 개발 환경에서 널리 사용된다. MVC 형식은 목적 코드의 재사용에 유용한 것은 물론, 사용자 인터페이스와 응용프로그램 개발에 소요되는 시간을 현저하게 줄여주는 형식이라고 많은 개발자들이 평가하고 있다.

MVC 형식은 소프트웨어 개발에 사용될 세 가지 구성요소 또는 객체를 제안한다.

모형 : 소프트웨어 응용과 그와 관련된 고급 클래스 내의 논리적 데이터 기반 구조를 표현. 이 목적 모형은 사용자 인터페이스에 관한 어떠한 정보도 가지고 있지 않다.

뷰 : 사용자 인터페이스 내의 구성요소들을 표현하는 클래스들의 집합 (누름단추, 표시 상자 등과 같이 사용자가 화면상에서 보고 응답할 수 있는 모든 것들)

제어기 : 모형과 뷰를 연결하고 있는 클래스들을 대표하며, 모형과 뷰 내의 클래스들 간에 통신하는데 사용됨
 
....간단히 말하면 입출력및 각동작을 분화시켜라..라는건데.....그다지 ...?

신고
Posted by naearu
으아~


if(preg_match("/[a-zA-Z0-9_]+/",$id) && preg_match("/[^a-zA-Z0-9_]+/",$id))

이거 한줄짜느라 꽤 고생했네 ㄱ-;;

흐~영문,숫자,언더바..를 제외한 문자가 들어오면 반응하는 솟스!!! ㄱ-;;

하으~ 아뒤검증하는것도 꽤나 짜증이 나는군하..





신고
Posted by naearu

-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
원본사이트: http://www.devshed.com/Server_Side/MySQL/Join/
      *  MySQL Table Joins  
    *(o) By W.J. Gilmore    
  *(o)|  July 06, 1999
 (o)| |  번역 : 원주희(lolol@shinan.hongik.ac.kr)
=======================================================================

[영어실력이 너무 부족하다보니 잘못된 부분이 있을 수도 있습니다.
고쳐야할 부분이 있으면 꼭 메일을 보내주세요.]

◆◆ 소개하기

SQL(Structured Query Language)의 가장 큰 특징 중의 하나는 여러개의 테이블을
연결시켜 데이터를 검색하거나 조작할 수 있는 기능이다. 이것은 데이터를 쉽고
빠르게 검색하고 불필요한 데이터를 줄여주는 장점이 있다. 다른 SQL 언어와 마찬
가지로 MySQL도 join명령어로 이 연산을 수행한다.

간단히 말하면 join은 두개 이상의 테이블로부터 필요한 데이터를 연결해 하나의
포괄적인 구조로 결합시키는 연산이다.

예를 들어, 한 컴퓨터 제조업자가 자신의 데이터를 능률적으로 관리하기 위한
데이터베이스가 필요하다고 하자. 이 데이터들은 주문, 고객, 생산과 같은 어떤
일관성있는 개념과 관련된 각각의 데이터들이 모여 다양하고 간결한 테이블들을
이룰 것이다. 테이블을 생성한 후에는, 다양한 예를 들어 데이터베이스에서 가장
많이 사용되는 join의 조작법에 대해 설명하겠다.

첫번째 테이블은 제조업자가 분류한 다양한 타입의 PC들의 데이터로 구성될 것이다.
----------------------------------------------
      mysql> create table pcs (
 -> pid INT,  // product id
 -> spec char(3),
 -> os char(10),
 -> ram INT,
 -> hd char(4)
 -> );
-----------------------------------------------

두번째 테이블은 제조업자의 다양한 고객들에 관한 데이터로 이루어질 것이다.
-----------------------------------------------
      mysql> create table clients (
 -> name char(25),
 -> cid char(8),     // client id
 -> email char(25),
 -> tel char(10)
 -> );
-----------------------------------------------

세번째 테이블은 주문 정보에 관한 데이타를 포함할 것이다.
-----------------------------------------------
      mysql> create table orders (
 -> order_date date,
 -> pid INT,
 -> cid char(8)
 -> );
-----------------------------------------------

◆◆ 자료(Data) 삽입하기

각각의 테이블에 아래와 같이 자료를 삽입해 보자.

☆ pcs (테이블1)
+------+------+-------+------+------+
| pid  | spec | os    | ram  | hd   |
+------+------+-------+------+------+
|    1 | 386  | Linux |   64 | 3.1  |
|    2 | 386  | Linux |  128 | 4.2  |
|    3 | 486  | WinNT |   64 | 3.1  |
|    4 | 586  | Linux |  128 | 4.2  |
|    5 | 586  | Win98 |  128 | 6.4  |
+------+------+-------+------+------+

[삽입방법]
-----------------------------------------------------------
      mysql> INSERT INTO pcs (pid, spec, os, ram, hd)
 -> VALUES (1, '386', 'Linux', 64, '3.1');
-----------------------------------------------------------

☆ clients (테이블2)
+--------+---------+---------------------------+------------+
| name   | cid     | email                     | tel        |
+--------+---------+---------------------------+------------+
| 원주희 | wjh-042 | haremoon@won.hongik.ac.kr | 123-456-78 |
| 홍길동 | hgd-043 | honggd@won.hongik.ac.kr   | 421-555-34 |
| 이쁘니 | pty-042 | pretty@won.hongik.ac.kr   | 459-555-32 |
| 못난이 | ugy-043 | ugly@won.hongik.ac.kr     | 439-555-88 |
+--------+---------+---------------------------+------------+

[삽입방법]
-----------------------------------------------------------
     mysql> INSERT INTO clients (name, cid, email, tel)
 -> VALUES ('원주희', 'wjh-042',
 -> 'haremoon@won.hongik.ac.kr', '123-456-7890');
-----------------------------------------------------------

☆ orders (테이블3)
+------------+------+---------+
| order_date | pid  | cid     |
+------------+------+---------+
| 1999-12-05 |    2 | wjh-042 |
| 1999-12-04 |    3 | hgd-043 |
| 1999-12-04 |    1 | wjh-042 |
| 1999-12-05 |    2 | wjh-042 |
| 1999-12-12 |    5 | ugy-043 |
| 1999-12-05 |    5 | pty-042 |
+------------+------+---------+

[삽입방법]
-----------------------------------------------------------
      mysql> INSERT INTO orders (order_date, pid, cid)
 -> VALUES ('1999-12-05', 2, 'wjh-042');
-----------------------------------------------------------

자, 이제부터 만들어진 3개의 테이블로부터 필요한 데이터만을 추출해 결합하는
방법에 대해 알아보자. 만일 당신의 상사가 특정한 날에 특정한 PC를 주문한 모든
고객의 이메일 목록을 원한다고 하자! 또는 특정한 고객에 의해 작성된 주문서에
있는 RAM의 양을 보고받기를 원한다고 하자. 이러한 모든 일들은 다양한 join문에
의해 쉽게 수행될 수 있다. 만들어진 테이블을 사용해 첫번째 join문을 생성해보고
작성해보자.

◆◆ The Cross Join

Cross Join은 가장 기본적인 join의 타입으로 한 테이블에 있는 각각의 열이 다른
테이블의 모든 열에 간단하게 매치되어 출력된다. 능률적이지는 않지만, 모든 join
의 공통된 특징을 나타내준다.   

Cross Join의 간단한 예 :
----------------------------------------------
mysql> SELECT * FROM pcs, clients;
----------------------------------------------

매우 많은 열들이 출력될 것이다. 테이블1(pcs)에 있는 각각의 열이 테이블2(clients)
의 모든 열에 매치된다는 것을 기억하자. 따라서, 3 열을 가진 테이블1(pcs)과 4 열을
가진 테이블2(clients)를 포함한 join문은 총 12 열의 테이블을 만들것이다. 

즉 cross-join은 테이블1에 있는 각각의 열들이 테이블2에 있는 모든열들을 한 번씩
교차해 출력한다고 기억하는 것이 쉬울 것같다.
  
첫번째 join을 성공적으로 수행했다면 다음의 예도 어렵지 않을 것이다.

아래의 예를 따라해 보고 어떤 결과가 출력될지 예상해보자.

-----------------------------------------------------------------------------
mysql> select c.name, o.cid from orders o, clients c where o.cid = "wjh-042";
-----------------------------------------------------------------------------

+--------+---------+
| name   | cid     |
+--------+---------+
| 원주희 | wjh-042 |
| 원주희 | wjh-042 |
| 원주희 | wjh-042 |
| 홍길동 | wjh-042 |
| 홍길동 | wjh-042 |
| 홍길동 | wjh-042 |
| 이쁘니 | wjh-042 |
| 이쁘니 | wjh-042 |
| 이쁘니 | wjh-042 |
| 못난이 | wjh-042 |
| 못난이 | wjh-042 |
| 못난이 | wjh-042 |
+--------+---------+

예상한 대로 결과가 출력되었나? clients 테이블에 있는 각각의 name이 orders테이
블의 "wjh-042"를 포함한 열마다 매치되어 출력되었다. 지금까지의 설명이 Cross
Join을 설명하는데 충분하지 않으므로 다른 질의를 사용해가며 JOIN을 활용해보기
바란다.

NOTE : 왜 테이블의 이름에 별명을 주어 사용할까? Aliases(별명)은 질의를 입력할
때 반복적인 키의 입력을 줄여주는 방법으로 사용되어진다. 따라서 열을 지정해 줄
때 반복적으로 'clients'를 한자 한자 입력하는 대신에, 질의내에 'from clients c'
를 지정해주고 'c'를 사용할 수 있다.

Cross Join이 테이블들을 연결해 주기는 하지만, 능률적이지는 못하다. 따라서
각각의 테이블들로 부터 우리가 원하는 데이타를 어떻게 하면 쉽게 선택할 수 있는지
계속 다음 장을 읽어보기 바란다.

◆◆ The Equi-join   

Equi-join은 한 테이블에 있는 어떠한 값이 두번째(또는 다수의) 테이블내에 포함된
값에 일치 할 때 수행된다.

product id 가 1인 PC를 주문한 고객의 목록을 원한다고 가정해 보자.

-------------------------------------------------------------------
   mysql> select p.os, c.name from orders o, pcs p, clients c
 -> where p.pid=o.pid and o.pid = 1 and o.cid=c.cid;
-------------------------------------------------------------------

+-------+--------+
| os    | name   |
+-------+--------+
| Linux | 원주희 |
+-------+--------+

◆ Non-Equi-join   

Equi-join은 다수의 테이블들 사이에서 일치하는 자료들만을 추출해낸다. 그러나
만일 일치하지 않은 자료들만을 추출해야 한다면...? 예를 들어, 당신의 상사가
주문한 pid가 제품의 pid보다 더 큰 order id의 모든 운영체제(OS)의 목록을
필요로 한다면 어떻게 할 것인가? 적당히 이름을 non-equi join라고 하겠다.

-------------------------------------------------------------------
mysql> SELECT p.os, o.pid from orders o, pcs p where o.pid > p.pid;
-------------------------------------------------------------------

+-------+------+
| os    | pid  |
+-------+------+
| Linux |    2 |
| Linux |    3 |
| Linux |    2 |
| Linux |    5 |
| Linux |    5 |
| Linux |    3 |
| Linux |    5 |
| Linux |    5 |
| WinNT |    5 |
| WinNT |    5 |
| Linux |    5 |
| Linux |    5 |
+-------+------+

orders 테이블의 pid가 pcs테이블의 pid보다 더 큰 모든 열들이 매치될 것이다.
주의깊게 살펴보면, 여러가지 제한을 준 간단한 cross-join 임을 파악할 수 있
을 것이다. 상사에게는 특별하게 유용하지 않을 지도 모르지만, 매우 유용한 기
능인 left join을 위한 준비 과정으로 생각하자. 자, 이제 다음장으로 가서
left join을 사용할 때 유용할 수있는 옵션들에 대해 집중적으로 알아보자.

◆◆ The Left Join

Left Join은 사용자가 어떠한 제한을 기반으로 관심있는 모든 종류의 자료를 추출
하게한다. 테이블 join중 가장 막강한 옵션으로, 테이블을 매우 쉽게 조작할 수
있게 한다.

만일 상사가 좀더 자세히, 자세히, 자세하게, 자세하게!를 외친다고 가정해보자.
left join이 우리의 문제를 해결해 줄 것이다.

-------------------------------------------------------------------
mysql> select * from orders left join pcs on orders.pid = pcs.pid;
-------------------------------------------------------------------

+------------+------+---------+------+------+-------+------+------+
| order_date | pid  | cid     | pid  | spec | os    | ram  | hd   |
+------------+------+---------+------+------+-------+------+------+
| 1999-12-05 |    2 | wjh-042 |    2 | 386  | Linux |  128 | 4.2  |
| 1999-12-04 |    3 | hgd-043 |    3 | 486  | WinNT |   64 | 3.1  |
| 1999-12-04 |    1 | wjh-042 |    1 | 386  | Linux |   64 | 3.1  |
| 1999-12-05 |    2 | wjh-042 |    2 | 386  | Linux |  128 | 4.2  |
| 1999-12-12 |    5 | ugy-043 |    5 | 586  | Win98 |  128 | 6.4  |
| 1999-12-05 |    5 | pty-042 |    5 | 586  | Win98 |  128 | 6.4  |
+------------+------+---------+------+------+-------+------+------+

고객이 주문한 모든 PC들의 목록을 추출해 낸다. 예를 들어, PHP3 또는 Perl
스크립트를 사용해 영수증을 출력하는데 사용할 수도 있다. 고객들에게 우리회
사로부터 구입한 모든 제품의 목록을 가끔씩 메일로 보내야 할 때에도
clients 테이블과 연결해 사용할 수 있을 것이다.

아래의 예에서 우리는 제품의 id(pid)가 3인 PC의 정보만을 볼 수 있다.

-------------------------------------------------------------------
mysql> select * from orders left join pcs on pcs.pid=3 and pcs.pid=orders.pid;
-------------------------------------------------------------------

+------------+------+---------+------+------+-------+------+------+
| order_date | pid  | cid     | pid  | spec | os    | ram  | hd   |
+------------+------+---------+------+------+-------+------+------+
| 1999-12-05 |    2 | wjh-042 | NULL | NULL | NULL  | NULL | NULL |
| 1999-12-04 |    3 | hgd-043 |    3 | 486  | WinNT |   64 | 3.1  |
| 1999-12-04 |    1 | wjh-042 | NULL | NULL | NULL  | NULL | NULL |
| 1999-12-05 |    2 | wjh-042 | NULL | NULL | NULL  | NULL | NULL |
| 1999-12-12 |    5 | ugy-043 | NULL | NULL | NULL  | NULL | NULL |
| 1999-12-05 |    5 | pty-042 | NULL | NULL | NULL  | NULL | NULL |
+------------+------+---------+------+------+-------+------+------+

◆ The Using Clause

left join에 약간의 옵션을 주어 둘 이상의 테이블에 있는 동일한 컬럼을 조금 더
깊게 연관지을수도 있다. on과 using옵션이 사용되며, 아래의 예제를 참조하자.


--------------------------------------------------------------------
## 원본의 예제는 아래와 같지만, 에러가 발생해 필자가 MySQL매뉴얼을 참조해
나름대로 수정을 했다.##
mysql> SELECT * from clients join on orders where clients.cid = orders.cid;
mysql> SELECT * from clients join on orders using (cid);
-------------------------------------------------------------------

==> 수정한 예제

-------------------------------------------------------------------
mysql> SELECT * from clients left join orders on clients.cid = orders.cid;
-------------------------------------------------------------------

또는 아래와 같이 나타낼 수도 있다.

-------------------------------------------------------------------
mysql> SELECT * from clients left join orders using (cid);
-------------------------------------------------------------------

두 예제 모두 똑같은 결과가 출력될 것이다.

+--------+---------+---------------------------+------------+------------+------+---------+
| name   | cid     | email                     | tel        | order_date | pid  | cid     |
+--------+---------+---------------------------+------------+------------+------+---------+
| 원주희 | wjh-042 | haremoon@won.hongik.ac.kr | 123-456-78 | 1999-12-05 |    2 | wjh-042 |
| 원주희 | wjh-042 | haremoon@won.hongik.ac.kr | 123-456-78 | 1999-12-04 |    1 | wjh-042 |
| 원주희 | wjh-042 | haremoon@won.hongik.ac.kr | 123-456-78 | 1999-12-05 |    2 | wjh-042 |
| 홍길동 | hgd-043 | honggd@won.hongik.ac.kr   | 421-555-34 | 1999-12-04 |    3 | hgd-043 |
| 이쁘니 | pty-042 | pretty@won.hongik.ac.kr   | 459-555-32 | 1999-12-05 |    5 | pty-042 |
| 못난이 | ugy-043 | ugly@won.hongik.ac.kr     | 439-555-88 | 1999-12-12 |    5 | ugy-043 |
+--------+---------+---------------------------+------------+------------+------+---------+   

다른 구문의 예를 적용해 가며 left join에 대해 이해하기 바란다. 공부를 하다보면
left join이 여러분의 개발활동에 매우 중요한 역할을 한 다는 것을 느낄 것이다.
테이블 join에 관한 정보를 좀더 깊게 교환하고 싶다면 http://www.mysql.com에 있는
다양한 토론 그룹을 체크해 보기 바란다.

◆◆ Self-joins
 
Self-join은 관리자가 하나의 테이블에 관련된 데이타를 집중시키는 막강한 방법을
제공해 준다. 사실, self-join은 그 자신의 테이블에 결합하는 것에 의해 수행된다.
개념의 이해를 위해 예를 들어 설명하겠다.

컴퓨터 워크스테이션을 만드는데 사용되는 하드웨어의 다양한 부품에 관한 정보를
가진 매우 큰 데이타베이스를 관리해야 한다고 가정하자. 워크스테이션은 데스크,
PC, 모니터, 키보드, 마우스등으로 이루어져 있다. 게다가, 데스크는 워크스테이션의
모두 다른 부분의 '부모'라고 생각될 수 있다. 우리는 각 워크스테이션의 레코드가
정확한 자료로 유지되기를 원할 것이며, 유일한 ID번호를 부여함으로써 워크스테이션
의 모든 부분을 구체적으로 관련시킬 것이다. 사실, 각 부분은 항목을 분명하게 해주는
유일한 ID번호와 그것의 부모(데스크) ID번호를 확인하기 위한, 두개의 ID 번호를
포함 것이다.

테이블이 아래와 같다고 가정하자.

mysql> select * from ws;
+---------+-----------+-----------+
| uniq_id | name      | parent_id |
+---------+-----------+-----------+
| d001    | desktop   | NULL      |
| m4gg    | monitor   | d001      |
| k235    | keyboar   | d001      |
| pc345   | 200mhz pc | d001      |
| d002    | desktop   | NULL      |
| m156    | monitor   | d002      |
| k9334   | keyboar   | d002      |
| pa556   | 350mhz pc | d002      |
+---------+-----------+-----------+


desktop은 그와 관련된 모든 부분들의 부모와 같으므로 parent_id를 가지고 있지
않음을 주목하자. 지금부터 유용한 정보를 위한 질의를 시작할 것이다. self-join
의 사용법을 쉽게 설명하기 위해 테이블을 간단하게 만들었다.

-------------------------------------------------------------------
mysql> select t1.*, t2.* from ws as t1, ws as t2;
-------------------------------------------------------------------

어떻게 출력되는가? 이전처럼, 첫번째 테이블의 각 열들이 두번째 테이블에 있는
모든 열들에 매치되어 연결되 출력될 것이다. 우리에게 매우 유용하지는 않지만
다시 한번 시도해보고 확인해 보기바란다. 좀더 재미있는 예를 들어보겠다.

-------------------------------------------------------------------
mysql> select parent.uniq_id, parent.name, child.uniq_id, child.name
    -> from ws as parent, ws as child
    -> where child.parent_id = parent.uniq_id and parent.uniq_id = "d001";
-------------------------------------------------------------------

흥미로운 결과가 출력될 것이다.
+---------+---------+---------+-----------+
| uniq_id | name    | uniq_id | name      |
+---------+---------+---------+-----------+
| d001    | desktop | m4gg    | monitor   |
| d001    | desktop | k235    | keyboar   |
| d001    | desktop | pc345   | 200mhz pc |
+---------+---------+---------+-----------+

self-join은 테이블의 자료를 검증하는 방법으로도 사용된다. 테이블내에 있는
uniq_id컬럼은 테이블에서 유일해야 하며, 만일 데이타의 엔트리가 깊어 뜻하지
않게 같은 uniq_id를 가진 두개의 항목이 데이타베이스에 입력된다면 좋지 않은
결과가 생길것이다. 이럴 경우 정기적으로 self-join을 사용해 체크할 수 있다.
우리는 350mhz pc의 uniq_id가 'm156'(이 값은 워크스테이션 'd002'에 속한
모니터의 uniq_id 값이다.)이 되도록 변경했다고 가정하자.

테이블의 내용은 다음과 같이 변경한다.
-------------------------------------------------------------------
mysql> update ws set uniq_id = 'm156' where name = '350mhz pc';
-------------------------------------------------------------------

아래의 예를 참고해 ws테이블에 self-join을 적용해보자.

-------------------------------------------------------------------
mysql> select parent.uniq_id, parent.name, child.uniq_id, child.name
    -> from ws as parent, ws as child
    -> where parent.uniq_id = child.uniq_id and parent.name <> child.name;
-------------------------------------------------------------------

아래와 같이 출력될 것이다.
+---------+-----------+---------+-----------+
| uniq_id | name      | uniq_id | name      |
+---------+-----------+---------+-----------+
| m156    | 350mhz pc | m156    | monitor   |
| m156    | monitor   | m156    | 350mhz pc |
+---------+-----------+---------+-----------+

Table join은 데이터베이의 관리를 쉽게 도와줄것이다. 구문의 이해를 정확하게
하기위해서 예제에서 배운 명령을 다양하게 변화시켜 적용해보기 바란다.




     




 

신고
Posted by naearu

13.2.7.2. UNION

SELECT ...

UNION [ALL | DISTINCT] SELECT ...

[UNION [ALL | DISTINCT] SELECT ...]

UNION 은 여러 개의 SELECT문을 하나의 결과 집합으로 결합 하기 위해 사용된다.

SELECT문에서 컬럼 이름들은 리턴될 결과에 대한 컬럼 이름으로써 사용된다. SELECT문에서 선택된 컬럼 들은 같은 데이터 형을 가져야 한다. (예를 들면, 첫 번째 문장에서 선택된 첫 번째 컬럼은 다른 문들에서 선택된 첫 컬럼과 같은 데이터 형을 가져야 한다.)

만일 SELECT 컬럼 들의 데이터 형이 일치 하지 않으면, UNION에서 컬럼들의 길이화 형들이 모든 SELECT문들에서 가져온 값들로 인식 된다. 예를 들면 다음과 같은 SQL문은:

mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);

+---------------+

| REPEAT('a',1) |

+---------------+

| a             |

| bbbbbbbbbb    |

+---------------+

(이전 버전의 MySQL에서 첫번째 SELECT로부터 그 형과 길이가 사용되고 두번째 레코드는 길이가 1로 변경될 것이다.)

SELECT 문은 일반적인 선택 문들이나 다음 과 같은 제한을 갖는다:

  • 오직 마지막 SELECT문만이 INTO OUTFILE을 사용할 수 있다.
  • HIGH_PRIORITY UNION의 부분들은 SELECT 문과 사용될 수 없다. 첫번째 SELECT에서 명시하면 어떤 영향도 있지 않게 된다.  뒤의 SELECT문들에 사용할 경우 문법 에러가 발생한다.

UNION의 기본 행동은 중복 레코드들이 그 결과에서 제거되는 것이다. DISTINCT 옵션 keyword역시 중복 레코드를 삭제 하도록 명시 하는 것이기 때문에 아무런 영향도 갖지 않는다. ALL 옵션 keyword를 사용하면 중복 레코드 제거는 발생하지 않으며 결과는 SELECT문에서 모든 매칭되는 레코드를 포함한다.

같은 질의 안에서 UNION ALL UNION DISTINCT를 사용할 수 있다. 혼합된 UNION 타입들은 DISTINCT UNION ALL UNION을 그것의 왼쪽으로 덮어 쓰도록 취급된다. DISTINCT UNION UNION DISTINCT을 사용하여 명시적으로 만들어지거나 DISTINCT ALL keyword없이 UNION을 사용하여 암시적으로 만들어 질 수 있다.

정렬을 위해 ORDER BY LIMIT절을 사용하기 위해서, 혹은 전체 UNION 결과를 제한 하기 위해 각 SELECT문을 괄호로 묶고 마지막에 ORDER BY LIMIT을 위치 시킨다. 다음 예제는 두 가지 절 모두를 사용한다.:

(SELECT a FROM t1 WHERE a=10 AND B=1)

UNION

(SELECT a FROM t2 WHERE a=11 AND B=2)

ORDER BY a LIMIT 10;

이런 종류의 ORDER BY는 테이블 이름을 포함하는 컬럼 참조들을 사용하지 않는다. (, tbl_name.col_name 포맷으로 명명한다) 대신, SELECT 문에서 컬럼 alias를 제공하고 ORDER BY에서 그 alias를 참조 한다. (대안적으로 그 컬럼 위치를 이용하는 ORDER BY안에서 컬럼을 참조 한다. 그러나 컬럼 위치의 사용은 반대 된다.)

또한 저장 되는 컬럼이 alias라면, ORDER BY 절은 컬럼 이름이 아닌 그 alias를 참조 해야 한다. 다음 문장들 중 처음 문장은 잘 수행되지만 두번째 문장은 Unknown column 'a' in 'order clause' 에러와 함께 실패 한다:

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;

(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;

개별 SELECT ORDER BY LIMIT를 적용하기 위해서는 SELECT를 괄호로 묶어 그 안에 절을 위치 시키도록 하라:

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)

UNION

(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

개별 SELECT문을 위한 ORDER BY의 사용은 기본적으로 UNION은 레코드 집합을 순서 없이 만들게 되기 때문에 최종 결과에서 레코드들이 어떻게 나타나야 하는지 순서에 관해 아무것도 암시 하지 않는다. ORDER BY LIMIT과 함께 쓰일 경우, 그것은 SELECT를 위해 가져온 선택된 레코드의 부분 집합을 결정하기 위해 사용된다.  그러나 그것은 최종 UION 결과에서 레코드들의 순서에 영향을 주지 않는다. ORDER BY가 한 SELECT문에서 LIMIT없이 나타나는 경우 아무런 영향을 갖지 않으므로 최적화는 되지 않는다..

UNION결과에 있는 레코드들을 순서대로 각 SELECT 에 의해 취해진 레코드들의 집합으로 구성되도록 하려면, 정렬 컬럼으로 사용하기 위해 각 SELECT문에서 추가적인 컬럼을 선택하고 마지막 SELECT뒤에 ORDER BY를 추가 하도록 하라:

(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)

UNION

(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;

또한 개별 SELECT 결과들 안에서 정렬 순서를 유지 하기 위해 ORDER by 절에 두 번째 컬럼을 추가 하도록 하라:

(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)

UNION

(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;

신고
Posted by naearu

<출처 : http://www.mysqlkorea.co.kr/sub.html?mcode=develop&scode=01&lang=k&m_no=21522&cat1=13&cat2=380&cat3=401>
MySQL
SELECT문 과 다중 테이블 DELETE 그리고 UPDATE문의 table_reference 부분을 위해 다음과 같이 JOINT을 지원한다:

table_references:
    table_reference [, table_reference] ...
 
table_reference:
    table_factor
  | join_table
 
table_factor:
    tbl_name [[AS] alias]
        [{USE|IGNORE|FORCE} INDEX (key_list)]
  | ( table_references )
  | { OJ table_reference LEFT OUTER JOIN table_reference
        ON conditional_expr }
 
join_table:
    table_reference [INNER | CROSS] JOIN table_factor [join_condition]
  | table_reference STRAIGHT_JOIN table_factor
  | table_reference STRAIGHT_JOIN table_factor ON condition
  | table_reference LEFT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [LEFT [OUTER]] JOIN table_factor
  | table_reference RIGHT [OUTER] JOIN table_reference join_condition
  | table_reference NATURAL [RIGHT [OUTER]] JOIN table_factor
 
join_condition:
    ON conditional_expr
  | USING (column_list)

하나의 테이블 참조는 하나의 JOIN 표현으로 알려져 있다.

table_factor 구문은 SQL 표준에 비해 확장 되었다. 후자는 한 쌍의 괄호 안의 리스트가 아닌 단지 table_reference를 받아들인다.

우리가 table_reference 아이템의 한 리스트 안의 각 콤마를 inner join과 동등하게 여긴다면 이것은 convervative extension이다. 예를 들면:

SELECT * FROM t1 LEFT JOIN (t2, t3, t4)
                 ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)

는 아래 문장과 동등하다:

SELECT * FROM t1 LEFT JOIN (t2 CROSS JOIN t3 CROSS JOIN t4)
                 ON (t2.a=t1.a AND t3.b=t1.b AND t4.c=t1.c)

MySQL에서, CROSS JOIN INNER JOIN과 동등하다. 표준 SQL에서는 그렇지 않다. INNER JOIN ON 절과 함께 쓰이며 CROSS JOIN은 그렇지 않다.

5.0.1이전의 MySQL에서는 table_references안의 괄호들이 생략되고 모든 join 연산들은 왼쪽으로 그룹지어진다. 일반적으로 괄호들은 단지 inner join연산을 포함하는 join 표현 안에서 무시 될 수 있다. 5.0.1부터는 nested join이 허락된다 (7.2.10“nested join optimization”부분을 참조하라.

join연산 에서 좀더 많은 변경들이 5.0.12에서 이루어 졌으며 MySQL을 표준 SQL을 따르도록 했다. 이들 변경들은 이 장의 후반부에서 설명된다.

다음 리스트는 join을 쓸 때 유념 해야 할 일반적인 사실들을 설명한다.

  • 테이블 참조는 tbl_name as alias_name 이나 tbl_name alias name을 사용하여 alias될 수 있다.
SELECT t1.name, t2.salary
  FROM employee AS t1 INNER JOIN info AS t2 ON t1.name = t2.name;
 
SELECT t1.name, t2.salary
  FROM employee t1 INNER JOIN info t2 ON t1.name = t2.name;
  • INNER JOIN 과 콤마(,) join 조건의 결여로 의미론적으로 동등하다. 양자는 명시된 테이블 사이에서 데카르트 곱을 만들어 낸다. (, 첫 번째 테이블의 각각 모든 레코드는 두 번째 테이블의 각각 모든 레코드와 join된다.)

그러나 콤마 연산자의 서열은 INNSER JOIN, CROSS JOIN, LEFT JOIN등 보다 낮다. Join 조건이 있는 경우 다른 join 형들과 콤마를 혼합하면 Unknown column ‘col_name’ in ‘on clause”의 형태의 에러가 발생한다. 이 문제 처리에 관한 정보는 이 장의 후반부에 다루어진다.

  • ON 조건은 WHERE 절에서 사용될 수 있는 형태의 조건 표현이다. 일반적으로 테이블들을 어떻게 join하는 지를 명시하는 조건을 위해선 ON조건을 결과 집합에서 어떤 레코드를 원하는 가에 대한 제한을 위해서는 WHERE절을 사용해야 한다.
  • LEFT JOIN에서 ON이나 USING부분에서 오른쪽 테이블과 매칭 되는 레코드가 없는 경우 모든 컬럼들이 NULL로 설정된 레코드가 오른쪽 테이블을 위해 사용된다. 다른 테이블과 대응을 갖지 못하는 테이블에서 레코드를 찾기 위해 이 사실을 사용할 수 있다.
SELECT table1.* FROM table1
  LEFT JOIN table2 ON table1.id=table2.id
  WHERE table2.id IS NULL;

이 예제는 table2에 나타나지 않은 id 값을 가지고 table1에서 모든 레코드를 찾는다.( 이것은 table1에 있는 모든 레코드가 table2에 있는 어떤 것과도 일치 하지 않는다.) 이것은 table2.id NOT NULL로 선언 되었음을 의미한다. 7.2.9“LEFT JOIN RIGHT JOIN 최적화부분을 참조 하라.

  • USING(column_list) 절은 양 테이블들에 존재해야 하는 컬럼들을 지정한다. 테이블 a b가 컬럼 c1, c2 그리고 c3를 포함하고 있다면 이어지는 join은 두 테이블의 컬럼들을 비교한다.
a LEFT JOIN b USING (c1,c2,c3)
  • 두 테이블의 NATURAL [LEFT] JOIN 은 두 테이블에 존재하는 모든 컬럼을 지정하는 USING절의 INNSER JOIN 이나 LEFT JOIN과 의미적으로 동일하도록 정의 된다.
  • RIGHT JOIN LEFT JOIN과 유사하게 작용한다. LEFT JOIN. 데이터베이스 들 간에 이식 가능한 코드를 유지 하기 위해서는 RIGHT JOIN보다 LEFT JOIN을 사용하는 것이 좋다.
  • JOIN문 설명에서 보여지는 { OJ ... LEFT OUTER JOIN ...} 문은 ODBC와의 호환성을 위해 존재 한다. 이 문장에서 중괄호는 정확히 쓰여져야 하는데 다른 구문 표현들에서 보여지는 포괄적 의미로 사용되는 것과는 다르다.
  • STRAIGHT_JOIN 은 왼쪽 테이블이 오른쪽 테이블보다 항상 먼저 읽힌 다는 점을 제외하면 JOIN과 동일하다. JOIN optimizer가 테이블을 잘못된 순서로 놓을 경우에 사용될 수 있다.

다음은 JOIN연산을 사용하는 예문들이다:

SELECT * FROM table1, table2;
 
SELECT * FROM table1 INNER JOIN table2 ON table1.id=table2.id;
 
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
 
SELECT * FROM table1 LEFT JOIN table2 USING (id);
 
SELECT * FROM table1 LEFT JOIN table2 ON table1.id=table2.id
  LEFT JOIN table3 ON table2.id=table3.id;

테이블로부터 정보를 가져올 때 MySQL이 사용할 인덱스에 대한 힌트를 제공 할 수 있다. USE INDEX (key_list)를 사용하여 MySQL이 테이블의 레코드들을 찾기 위해 가능한 인덱스들중 단지 하나만 사용하도록 할 수 있다. 선택적 구문인 IGNORE INDEX(key_list)문은 MySQL이 특정 인덱스를 사용하지 못하도록 할 수 있다. 이러한 힌트들은 EXPLAIN문이 MySQL이 인덱스들 중 잘못된 인덱스를 사용하고 있다는 것을 보여준다면 유용하다.

여러분은 FORCE INDEX 문을 사용 할 수 있는데 이것은 USE INDEX(key_list)와 같이 작용하며 테이블 스캔이 추가적이다. , 테이블에서 레코드를 찾기 위해 주어진 인덱스들을 사용할 수 없는 경우에만 테이블 스캔이 사용될 수 있다.

USE INDEX, IGNORE INDEXFORCE INDEX 문은 테이블에서 레코드를 어떻게 찾고 JOIN을 하기 위해 어떻게 해야 하는지 MySQL이 결정 할 때에 어떤 인덱스들이 사용될 것인지에 영향을 미친다. 이들은 ORDER BY GROUP BY를 결정할 때 사용할 인덱스에는 영향을 주지 않는다.

USE KEY, IGNORE KEY FORCE KEY USE INDEX, IGNORE INDEX, FORCE INDEX 와 동일하다.

:

SELECT * FROM table1 USE INDEX (key1,key2)
  WHERE key1=1 AND key2=2 AND key3=3;
 
SELECT * FROM table1 IGNORE INDEX (key3)
  WHERE key1=1 AND key2=2 AND key3=3;

MySQL 5.0.12에서 변경된 JOIN연산

MySQL 5.0.12에서 natural joins 과 외부 join 변수들을 포함한 USING을 사용한 join SQL:2003 표준에 따라 처리 된다. 그 목적은 MySQL의 구문들과 의미들을 SQL:2003에 따라 NATURAL JOIN JOIN… USING 을 조절하는 것이다. 그러나 이들 join연산에서의 변화들은 어떤 join들에 대해서는 다른 출력물을 결과로 내놓을 수 있다. 또한 이전 버전들에서 정확히 동작하는 것처럼 보여진 몇몇 질의들이 표준에 맞게 새롭게 씌여 져야만 한다.

이들 변화들은 다섯 가지 주요 측면을 가지고 있다:

  • MySQL NATURAL 혹은 USING Join 연산에서 결과 컬럼을 결정하는 방법(이는 전체 FROM절의 결과이다.)
  • SELECT * SELECT tbl_name.* 의 선택된 컬럼 들의 리스트로의 확장.
  • NATURAL USING join에서 컬럼 이름들의 결정.
  • NATURAL 이나 USING 에서 JOIN ... ON. 으로의 전이
  • JOIN…ON에서 ON조건에 있는 컬럼 이름의 결정.

다음의 리스트는 join 연산에 관한 5.0.12에서의 변화의 몇 가지 효과에 관한 상세한 정보를 제공한다. “previously”의 의미는 “MySQL 5.0.12 이전 을 의미한다.

  • NATURAL 이나 USING join의 컬럼들은 이전 버전과 다를 수 있다. Redundant한 결과들은 더 이상 나타나지 않으며 SELECT *확장에서의 컬럼 순서는 전과 다를 수 있다.

다음 문장들을 고려해 보자:

CREATE TABLE t1 (i INT, j INT);
CREATE TABLE t2 (k INT, j INT);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t2 VALUES(1,1);
SELECT * FROM t1 NATURAL JOIN t2;
SELECT * FROM t1 JOIN t2 USING (j);

이전 버전에서 문장들은 다음 결과를 만들어 낸다.

+------+------+------+------+
| i    | j    | k    | j    |
+------+------+------+------+
|    1 |    1 |    1 |    1 |
+------+------+------+------+
+------+------+------+------+
| i    | j    | k    | j    |
+------+------+------+------+
|    1 |    1 |    1 |    1 |
+------+------+------+------+

처음 SELECT문에서는 컬럼 i가 양쪽 테이블들에 나타나며 표준 SQL에 따라 join 컬럼이 되는데 output에서 단지 한번만 나타 나야 한다. 두번째 SELECT문 역시 유사하게 컬럼 j USING절 안에서 몇 명되고 output으로 한번만 나와야 한다. 그러나 두가지 경우 모두 redundant 컬럼이 제거 되지 않는다. 또한 컬럼들의 순서도 표준 SQL과 정확히 일치 하지 않는다.

이제 결과물들은 아래와 같은 결과를 생산 한다.:

+------+------+------+
| j    | i    | k    |
+------+------+------+
|    1 |    1 |    1 |
+------+------+------+
+------+------+------+
| j    | i    | k    |
+------+------+------+
|    1 |    1 |    1 |
+------+------+------+

Redundant 컬럼이 제거 되고 컬럼 순서가 정확하게 표준 SQL을 따른다.:

    • 첫번째로, 두개의 join된 테이블들의 일반 컬럼들을 첫번째 테이블의 컬럼 들 순서에 따라 합체 시킨다.
    • 두번째로, 컬럼들은 첫 번째 테이블에서의 순서대로 유일하게 되어야 한다.
    • 세번째로, 컬럼들은 두 번째 테이블에서의 순서대로 유일하게 되어야 한다.

두개 일반 컬럼들을 대체하는 하나의 결과 컬럼은 COALESCE연산을 통해정의 된다. t1.a t2.a의 단일 join 컬럼은 a로 정의 되는데 구문은

a = COALESCE(t1.a, t2.a)과 같다. where:

COALESCE(x, y) = (CASE WHEN V1 IS NOT NULL THEN V1 ELSE V2 END)

만일 join연산이 다른 join연산이라면 그 join의 결과 컬럼들은 join된 테이블들의 모든 컬럼의 연결로 이루어 진다. 이것은 이전 버전의 MySQL와 동일하다.

coalesced컬럼의 정의에 대한 결과는 그 컬럼이 두개의 컬럼중 하나가 항상NULL이라면 coalesced컬럼은 NULL이 아닌 컬럼의 값을 포함한다. 두 컬럼이 NULL이거나 NULL이 아닌경우, 양쪽 일반 컬럼들은 같은 값을 갖게 되고 coalesced 컬럼의 값으로 어떤 것이 선택 되었는지는 문제가 되지 않는다. 이것을 해석하는 가장 간단한 방법은 outer join coalesced컬럼이 JOIN JOIN inner테이블의 일반 컬럼에 의해 재 표현 된다. 다음 두개의 테이블 t1(a,b) t2(a,c)이 다음과 같은 값을 가지고 있다면::

t1    t2
----  ----
1 x   2 z
2 y   3 w

그러면:

mysql> SELECT * FROM t1 NATURAL LEFT JOIN t2;
+------+------+------+
| a    | b    | c    |
+------+------+------+
|    1 | x    | NULL |
|    2 | y    | y    |
+------+------+------+

a컬럼의 값은 t1.a를 포함하고 있다.

mysql> SELECT * FROM t1 NATURAL RIGHT JOIN t2;
+------+------+------+
| a    | c    | b    |
+------+------+------+
|    2 | y    | y    |
|    3 | z    | NULL |
+------+------+------+

여기에서 컬럼 a t2.a의 값을 포함 하고 있다.

이들 결과들을 다른 JOIN…ON을 가진 동등한 질의들과 비교하면

mysql> SELECT * FROM t1 LEFT JOIN t2 ON (t1.a = t2.a);
+------+------+------+------+
| a    | b    | a    | c    |
+------+------+------+------+
|    1 | x    | NULL | NULL |
|    2 | y    |    2 | y    |
+------+------+------+------+
mysql> SELECT * FROM t1 RIGHT JOIN t2 ON (t1.a = t2.a);
+------+------+------+------+
| a    | b    | a    | c    |
+------+------+------+------+
|    2 | y    |    2 | y    |
| NULL | NULL |    3 | z    |
+------+------+------+------+
  • 이전 버전에서, USING절은 다음 컬럼들을 비교 하기 위해 ON절로 다시 쓰여 질 수 있다. 예를 들면, 다음 두 절들은 의미적으로 동일하다.:
a LEFT JOIN b USING (c1,c2,c3)
a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3

이제 두 절들은 더 이상 같지 않다:

    • join조건을 어떤 레코드가 만족 시키는지를 결정하는 것과 관련하여 두가지 모두의 join은 의미적으로 동일하다.
    • SELECT * 확장을 위해 어떤 컬럼을 display할지 결정하는 것과 관련하여 두개의 join은 의미적으로 동일 하지 않다. USING join ON join이 모든 테이블로부터 모든 컬럼을 선택하는데 반해, 컬럼들 중 coalesced 값을 선택한다. USING join에 선행자로 SELECT* 는 이들 값들을 선택한다:
COALESCE(a.c1,b.c1), COALESCE(a.c2,b.c2), COALESCE(a.c3,b.c3)

ON join을 위해 SELET * 문이 이들 값들을 선택한다.

a.c1, a.c2, a.c3, b.c1, b.c2, b.c3

inner join과 함께 COALESCE(a.c1,b.c1) 는 두 컬럼 모두가 같은 값을 갖게 되므로 a.c1 b.c1은 같게 된다. Out join 에서 두 컬럼들중 하나가 NULL이 될 수 있다. 그 컬럼은 결과에서 삭제 될 것이다.

  • 다중 natural join에 대한 평가는 질의를 다시 쓰도록 요구하는  NATURAL이나 USING join의 결과에 영향을 미치는 매우 중요한 방법 에서 다르다. 예를 들어 세개의 테이블 t1(a,b), t2(c,b) 그리고 t3(a,c)가 있고 각각의 테이블은 t1(1,2), t2(10,2) 그리고 t3(7,10)으로 하나의 레코드를 갖는다고 가정하자. 또한 세개의 테이블들에서 다음과 같이 NATURAL JOIN을 갖는다고 가정해보자:
SELECT ... FROM t1 NATURAL JOIN t2 NATURAL JOIN t3;

이전 버전의 MySQL에서는 그 문장이 nested join (t1 NATURAL JOIN t2)이므로 두번째 JOIN의 연산 대상자는 t2로 인식되었다. 결과적으로 t3의 컬럼들은 t2에서 일반 컬럼들로 체크되고 t3 t1과 함께 일반 컬럼들을 갖는다면 이들 컬럼들은 equi-join컬럼 들로 사용되지 않는다. 따라서 이전버전의 MySQL에서는 선행적인 질의가 다음 equi-join으로 변환 된다.:

SELECT ... FROM t1, t2, t3
  WHERE t1.b = t2.b AND t2.c = t3.c;

JOIN (t1.a = t3.a) 동등 질의 속성을 빠뜨리고 있다. 결과적으로 그것이 가져야 할 empty 결과를 갖지 못하고 하나의 레코드를 생산한다. 정확한 동등 질의는 다음과 같다:

SELECT ... FROM t1, t2, t3
  WHERE t1.b = t2.b AND t2.c = t3.c AND t1.a = t3.a;

여러분이 이전 버전과 현재 버전에서 같은 결과를 갖는 질의를 요구한다면 첫번째 동등 join으로 natural join을 다시 쓰도록 하라.

  • 이전 버전에서, 컴마 연산자(,) JOIN 연산자 모두는 같은 우선 순위를 가졌다. 따라서 join 연산 t1,t2 JOIN t3 ((t1,t2) JOIN t3)로 해석 되었다. 현재 버전은 JOIN이 좀더 높으며 따라서 그 SQL문은 (t1, (t2 JOIN t3))로 해석 된다. 이 변경은 ON절을 사용하는SQL문들에 영향을 주는데 그 절이 JOIN의 피 연산자 안에 있는 컬럼 들만을 참조 할 수 있고 우선순위의 변화는 그들 피 연산자의 해석에 변화를 주기 때문이다.

:

CREATE TABLE t1 (i1 INT, j1 INT);
CREATE TABLE t2 (i2 INT, j2 INT);
CREATE TABLE t3 (i3 INT, j3 INT);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t2 VALUES(1,1);
INSERT INTO t3 VALUES(1,1);
SELECT * FROM t1, t2 JOIN t3 ON (t1.i1 = t3.i3);

이전 버전에서 SELECT t1,t2 (t1,t2)와 같이 암시적 그룹으로 인식 하므로 문법적으로 맞다. 현재 버전에서는 JOIN이 우선순위를 가지며 ON 절에 있는 피 연산자로 t2 t3가 된다. t1.i1 t2 t3에 속한 컬럼 조건에 해당 하지 않으며 이는 Unknown column ‘t1.i1’ in ‘on clause’ 에러를 만들게 된다. JOIN이 처리 되도록 하기 위해서는 처음 두 테이블을 괄호로 그룹을 만들어 주어야 하며 이렇게 되면 ON절의 피 연산자는 (t1,t2) t3가 된다:

SELECT * FROM (t1, t2) JOIN t3 ON (t1.i1 = t3.i3);

콤마 연산자의 사용을 피하고 JOIN연산을 대신 쓸 수 이다.

SELECT * FROM t1 JOIN t2 JOIN t3 ON (t1.i1 = t3.i3);

이 변경은 INNER JOIN, CROSS JOIN, LEFT JOIN, 그리고 RIGHT JOIN 와 콤마 연산자가 혼합된 SQL문에 적용 되며 이들 모두는 콤마 연산자보다 높은 우선순위를 갖는다.

  • 이전 버전에서 ON 절은 오른쪽에 있는 테이블 안에 있는 컬럼 들을 참조 할 수 있었으나 현재 버전에서는 오직 피 연산자들만 참조 할 수 있다.

:

CREATE TABLE t1 (i1 INT);
CREATE TABLE t2 (i2 INT);
CREATE TABLE t3 (i3 INT);
SELECT * FROM t1 JOIN t2 ON (i1 = i3) JOIN t3;

이전 버전에서 SELECT문은 맞는 표현이었으나 현재 버전에서는 Unknown column 'i3' in 'on clause' 에러와 함께 실패한다. i3 컬럼이 t3 안에 없기 때문인데 이는 ON절의 피 연산자가 아니다. 이 문장은 다음과 같이 다시 쓰여져야 한다.

SELECT * FROM t1 JOIN t2 JOIN t3 ON (i1 = i3);
  • NATURAL이나 USING join들 안에서 컬럼 이름 들의 결과는 이전 버전과 다르다. FROM절의 외부에 있는 컬럼 이름들에 대해, MySQL은 이전 버전과 대비 되는 질의들의 집합을 다룬다. , MySQL이 어떤 컬럼이 모호 하다는 에러를 공식적으로 발생 시킬 경우, 그 질의는 정확히 다루어 진다. 이것은 MySQL이 이제 NATURAL 이나 USING join의 일반 컬럼 들을 하나의 컬럼으로 다루기 때문이며 따라서 한 질의가 그런 컬럼 들을 참조할 경우 질의 compiler는 그것들을 모호하게 여기지 않는다.

:

SELECT * FROM t1 NATURAL JOIN t2 WHERE b > 1;

이전 버전에서 이 질의는 ERROR 1052 (23000): Column 'b' in where clause is ambiguous 에러를 출력한다. 현재 버전에서 질의는 다음과 같이 정확한 결과를 출력한다:

+------+------+------+
| b    | c    | y    |
+------+------+------+
|    4 |    2 |    3 |
+------+------+------+

SQL:2003표준과 비교하여 MySQL에서의 확장은 MySQL NATURAL이나USING join common 컬럼 들을 조절 할수 있게 하였는데 이는 표준 SQL문에서는 허용되지 않는다.

신고
Posted by naearu