레이블이 MySQL인 게시물을 표시합니다. 모든 게시물 표시
레이블이 MySQL인 게시물을 표시합니다. 모든 게시물 표시

2016년 7월 6일 수요일

MySQL에서 URL Decoding 하는 SQL Stored Procedure.

MySQL에서 URL Decoding 하는 SQL Stored Procedure.

데이터 입력을 encode된걸 넣어서 - 게다가 중간중간 깨진데이터들이나 URL일부가 그대로 들어가있는 경우도 있었고 (물론 매우 소수 일부가 그러했다.)아무튼 그런 이유로 어쩔 수 없이 검증하는 쿼리가 필요했다. (등떠밀려 만듦ㅎ)

아래는 최초 적용한 함수이다.
근데.. 이게 영 이상하게 동작한다. 실패작이다.
(그냥 된다카길래 가져다 썼는데 이거 원;)

  1. DELIMITER $$  
  2.   
  3. DROP FUNCTION IF EXISTS `url_decode` $$  
  4. CREATE DEFINER=`root`@`%` FUNCTION `url_decode`(original_text TEXT) RETURNS TEXT CHARSET utf8  
  5. BEGIN  
  6.     DECLARE new_text TEXT DEFAULT NULL;  
  7.     DECLARE pointer INT DEFAULT 1;  
  8.     DECLARE end_pointer INT DEFAULT 1;  
  9.     DECLARE encoded_text TEXT DEFAULT NULL;  
  10.     DECLARE result_text TEXT DEFAULT NULL;
  11.     DECLARE EXIT HANDLER FOR SQLEXCEPTION
  12.     BEGIN
  13.         return NULL;
  14.     END;

  15.     SET new_text = REPLACE(original_text,'+',' ');  
  16.     SET new_text = REPLACE(new_text,'%0A','\r\n');  
  17.    
  18.     SET pointer = LOCATE("%", new_text);  
  19.     while pointer <> 0 && pointer < (CHAR_LENGTH(new_text) - 2) DO  
  20.         SET end_pointer = pointer + 3;  
  21.         while MID(new_text, end_pointer, 1) = "%" DO  
  22.             SET end_pointer = end_pointer+3;  
  23.         END while;  
  24.    
  25.         SET encoded_text = MID(new_text, pointer, end_pointer - pointer);  
  26.         SET result_text = CONVERT(UNHEX(REPLACE(encoded_text, "%""")) USING utf8);  
  27.         SET new_text = REPLACE(new_text, encoded_text, result_text);  
  28.         SET pointer = LOCATE("%", new_text, pointer + CHAR_LENGTH(result_text));  
  29.     END while;  
  30.    
  31.     return new_text;  
  32.   
  33. END $$  
  34.   
  35. DELIMITER ;


그래서 다른 것을 찾아보았다.
그래서 아래와 같은 함수를 발견하게되었고 이번엔 꼼꼼하게 소스를 다 훝어보았다.
먼저 소스보다 훨씬 더 가독성이 좋았고 편리하게 작성되어있어 수정도 편했다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
DROP FUNCTION IF EXISTS urldecode;

DELIMITER |

CREATE FUNCTION urldecode (s VARCHAR(4096)) RETURNS VARCHAR(4096)
DETERMINISTIC 
CONTAINS SQL 
BEGIN
       DECLARE c VARCHAR(4096) DEFAULT '';
       DECLARE pointer INT DEFAULT 1;
       DECLARE s2 VARCHAR(4096) DEFAULT '';
       DECLARE h3 VARCHAR(4096) DEFAULT '';
       DECLARE CONTINUE handler FOR 1366
       BEGIN
       END;

       IF ISNULL(s) THEN
          RETURN NULL;
       ELSE
       SET s2 = '';
       WHILE pointer <= LENGTH(s) DO
          SET c = SUBSTR(s,pointer,1);
          IF c = '+' THEN
             SET h3 = '20';
          ELSEIF c = '%' AND pointer + 2 <= LENGTH(s) THEN
                   SET h3 = UPPER(SUBSTR(s,pointer+1,2));
                   SET pointer = pointer + 2;
          ELSE
                   SET h3 = HEX(c);
          END IF;
          SET s2 = CONCAT(s2,h3);
          SET pointer = pointer + 1;
       END while;
       END IF;
       RETURN UNHEX(s2);
END;

|

DELIMITER ;

헌데, 이넘도 문제가 있다.

encode data가 깨진 경우, 마지막 RETURN UNHEX(s2); 에서 1366 오류가 난다.
이해가 가지 않는다; ㅠㅠ;;;;;;;;;;;;;;;;

일단 작업에 방해가 되면 안되니, 위 소스처럼
DECLARE CONTINUE handler FOR 1366
BEGIN
END;
로서 땜빵.

문제의 진짜 이유를 찾기 위해 테스트해 보았다.

결국, 수십여분 삽질끝에.. 이상한것을 발견했다. 이유는 모른다. 

RETURN UNHEX(s2); #1366 ERROR 발생
위 부분을 
RETURN s2;

위와 같이 UNHEX 배제 후 함수 호출부분에서 UNHEX하니 

SELECT urldecode('%ED%81%AC%EBCsn%3D3%7Chk%3Dbbcac20f524e408ffbd748bce750e921a2aca717'); #1366 ERROR 발생 

SELECT UNHEX(urldecode('%ED%81%AC%EBCsn%3D3%7Chk%3Dbbcac20f524e408ffbd748bce750e921a2aca717'));


결과가 나왔다. 응?! 왜지?!
return되기직전에 unhex를 사용하면 안되고 반환반고나서 unhex를 쓰면된다?!

SQL 잘하는 사람한테 물어봐야할라나..?

아는사람은 좀 알려주세요~~~~ ㅠㅠ



2016년 2월 16일 화요일

유니크인덱스와 PK의 차이점? - 다음팁

출처: 다음팁

Question:
유니크인덱스와 PK의 차이점?


PK와 유니크 인덱스의 차이점은 뭔가요?
테이블에서 FK를 사용하지 않는다면 유닉스 인덱스 만으로도 가능한데..
굳이 PK를 잡는 이유는 뭔지 알고 싶습니다.
테이블을 대표하는 것을 나타내기위해 PK를 쓴다는 말이 있는데...
이건 유닉스 인덱스로 대치 할 수 없는건가요?
PK와 유니크 인덱스 중 유니크인덱스로만 구성했을때 퍼포먼스가 더 빠르다고 하던데 맞는 말인지 알고 싶습니다. 맞다면 어떻게 해서 더 빠른지두 알고 싶습니다.



Answer:


안녕하십니까? 엔코아 정보컨설팅에 근무하는 컨설턴트 조시형입니다.

우선 Primary Key와 Unique Index의 차이점을 설명하는 것은 부적절하다는 말씀을 드리고 싶습니다. 둘간의 상관관계를 설명하는 것이 맞는 개념입니다. 많은 개발자들이 PK는 왠지 부하를 준다는 잘못된 선입견을 가지고 있고 따라서 PK 대신 Unique Index를 사용하는 것으로 알고 있는데 매우 그릇된 관행(?)이라고 생각합니다. 따라서 앞에서 다른 분들이 좋은 설명 많이 해 주셨지만 부연해서 설명을 드리도록 하겠습니다.

Primary Key라고 하는 것은 논리적인 개념입니다. Primary Key는 해당 컬럼이 그 테이블의 식별자임을 나타내는 것으로서, 자신과 다른 레코드가 서로 다른 인스턴스임을 확인할 수 있게 해 주는 역할을 합니다. 즉, 해당 그 레코드의 존재자체인 것이지요. 

원래 사람이름이라는 것이 '나'와 다른 사람을 식별하기 위해 사용하는 것인데, 다른 사람과 중복될 수 있으므로 나를 식별할 수 있는 속성으로서 주민등록번호라는 것을 대신 사용합니다. 따라서 주민등록번호는 나와 별개가 아닌 나의 존재 그 자체입니다. 철학적으로는 맞지 않는 설명이겠지만 적어도 ‘데이터의 세계’에서는 그렇습니다.

반면 PK constraint는 물리적인 개념입니다. "이 컬럼(들)은 다른 레코드와 구분짓는 식별자 역할을 하는 중요한 컬럼이므로 데이터는 중복을 허용해서는 안 되고(unique), null값을 허용해서도 안돼(not null)"라고 DB에게 정보를 주는 것입니다. primary key constraint를 설정하면 unique index와 not null constraint가 자동적으로 생성되는 이유도 여기에 있지요. 

특히 인덱스는 PK 컬럼의 Unique성을 보장하기 위해 매우 필수적인 도구인데, 만약 인덱스 없이 해당 컬럼값이 중복되지 않도록 할 수 있는 방법을 생각해 보시기 바랍니다. 잘 떠오르지 않을 것입니다. 결론적으로 말씀드리면, 인덱스와 PK의 상관관계에 있어서 Unique이든 Non-Unique이든 Index라는 놈은 PK 컬럼의 Unique성을 보장하기 위해 사용하는 하나의 도구(Tool)에 지나지 않습니다. 

어떤 의미에서만 본다면, 어느 한 컬럼에 Not Null Constraint를 주고, 그 컬럼에 Unique Index를 생성하였다면 primary key와 다를 것이 하나도 없어 보입니다. 하지만 primary key는 데이터베이스와 사용자 입장에서 매우 중요한 정보 역할을 하기 때문에 중요하다고 말씀드리고 싶습니다. 

앞서 말씀드렸듯이, 원래 primary key는 “이 컬럼(들)이 테이블의 식별자(identifier)이므로 중복을 허용해서는 안 되고, null값을 허용해서도 안 된다”라는 의미론적(semantic) 인 의미에서 정의하는 것이며, DBMS는 이를 효과적으로 처리하기 위해서 index를 자동생성해서 사용하고 not null constraint를 정의하는 것입니다. 

참고로 primary key를 위해서 반드시 unique index가 필요한 것은 아닙니다. non-unique index만 있더라도 새로운 값이 들어올 때 중복값이 있는지 체크하는 데에는 전혀 문제가 없으므로 기존에 이미 non-unique 인덱스가 정의되어 있는 상황이었다면 그 인덱스를 그대로 사용합니다. DW 시스템에서 대량의 데이터 로딩시 속도를 빠르게 하기 위해 PK Constraint를 일시적으로 Disable 시키는 경우가 있는데 이렇게 되면 Unique Index도 동시에 제거되므로 인덱스를 다시 생성해야 하는 부담이 생깁니다. 이러한 부담을 덜기 위해 의도적으로 non-unique index를 생성하는 경우가 있는데 이에 대해서는 더 깊이 언급하지 않겠습니다.
하여튼 primary key, foreign key, not null 등과 같은 integrity constraint 정보들은 plan을 생성하고, query rewrite(주로 DW에서 많이 사용되는 기능임)를 수행할 때, 그리고 기타 여러가지 용도로 데이터베이스에 의해 사용되어집니다. 

그리고 OLAP Tool과 같이 데이터베이스에 접근하는 여러 tool들이 동적으로 ad-hoc query를 생성할 때 이 정보들을 활용합니다. optimizer와 tool 입장에서 뿐만 아니라 데이터베이스를 사용하는 사용자 입장에서도 실제 document 역할을 하게 되므로 의미가 있습니다. ER Diagram을 보지 않고 data dictionary에 있는 정보만을 보고도 그 테이블의 식별자(Identifier)가 어떤 컬럼으로 구성되어 있는지 쉽게 확인할 수 있잖아요. 이런 좋은 기능과 역할을 하는데도 불구하고 unique index와 not null 만을 정의해서 primary key 기능을 대신하도록 할 이유는 없지 않을까요? 

성능과 관련해서 말씀드리면, Not Null Constraint와 Unique 인덱스를 PK Constraint 대신 사용하는 것이 더 속도가 빠르다는 것은 전혀 근거없는 낭설에 불과합니다. 오히려 SQL 옵티마이저에게 더 많은 정보를 제공함으로써 더 좋은 실행계획을 만드는데 일조하게 되고 따라서 더 빨라지는 경우가 많겠지요...

2003.12.02



음.. 좋은 글 잘읽고 갑니다..
그리구요..
PK와 유니크 인덱스 중에서 유니크 인덱스가 퍼포먼스가 빠르다는 말은요..
아마두 이런 경우가 아닐까 생각이 됩니다..
일단 위에서도 말씀 하셨드시 유니크 인덱스는 null 값을 입력 할수 있습니다.
즉 index를 생성하고 scan 할때 null에 대해서는 index를 만들지 않기 때문에 더 빠르다는 말이 나오지 않았을까 생각이 되는군요..
예로 어떤 특정 값을 입력할때 defalut value로 '9999999'이런 값이 들어 가는 것과 그냥 null이 들어 갈 경우, '9999999'인 경우를 많이 select하지 않는다면 디폴터로 특정 값을 넣지 않는 경우와 유사하죠..
null을 빼고 index를 구성하니까 당연히 빠르죠..
이상.. 주제와는 좀 벗어난듯 하네요.. 지송..

2003.12.02




안녕하세요.. 이노입니다.

궁금해하시는 내용에 대한 답변은 예전 좀 다른 문제로 제가 답변을 올렸던 경우와
유사한 듯 하여 그때 내용을 간략하게 다시 올리겠습니다.
먼저 PK Index와 Unique Index의 차이는 간단하게 Nullable의 차이라고 하겠습니다.
쉽게 말해서 PK Index라는 것은 Unique Index + Not Null을 의미합니다.
반대로 Unique Index는 인덱스가 걸리는 필드에 대해서도 Null을 허용하죠. 

즉, 특정 테이블의 컬럼에 대해 Unique 인덱스가 있다고 해서, 해당 필드에 Null 값을
Insert 못하지는 않습니다. 하지만, PK Index가 설정되어 있다고 한다면 자동으로
해당 필드에 대한 Not null 제약조건이 생기기 때문에 Null을 insert할 수 없죠.

이러한 이유로 인해, SQL의 경우에 따라서는 Unique Index임에도 불구하고 Table
Access를 하는 예도 있습니다. 해당 값이 Not Null임을 보장하지 못하기 때문이죠.
따라서 SELECT문의 경우 때로는 오히려 Unique보다 PK가 아주 근소한 차이지만 더
빠른 경우도 있습니다. 물론, INSERT의 경우 제약조건에 대한 체크로 인해 조금 더
느릴(?)수도 있겠지요..

실제 테스트를 해봐도, 특정 field의 값에서 max값을 추출하고자 하는데 null이 포함되어 있으면 실제로 index search에서 찾은 값이 null인지 값을 가지고 있는지는 테이블을 뒤져봐야 알 수 있는 정보가 됩니다. 

그래서 PK Index인 경우에는 (null을 가진 필드가 없음을 보장해주기 때문에..)index 영역안에서 결과 값을 리턴해줄 수 있고, Unique의 경우에는 데이터 영역까지 가서 실제 값을 확인해봐야 하는 결과가 나옵니다.
(이러한 경우도 Analyze나 테이블에 대한 정확한 통계가 있다면 그렇지 않을수도..)

이상 짧은 제 소견이였습니다.
원하시는 답변이 어느 정도 되셨는지 모르겠습니다.

행복한 하루 되시기를~~

2003.12.02




PK와 유니크 인덱스는 비교 하기엔 좀 무리가 있다고 보는데요, Table 생성시 PK에 자동적으로 유니크 인덱스가 생성 됩니다. 일반적인 유저가 생성하는 인덱스는 유닉스 인덱스로 만들지 않는것이 좋습니다. 

만일 PK없이 유저가 유니크 인덱스만 만들었다고 해도 PK를 대신할수는 없습니다.
옵티마이져가 실행계획시 인덱스 안타고 FTS 하면 인덱스는 아무 소용이 없는거죠.
인덱스와 키는 개념 자체가 틀린겁니다. 

테이블에서 FK를 사용 하지 않아도 PK는 필요합니다.
이유를 말하자면 모델링 측면에서는 Relational 개념에 부합하는거겠고 Database측면으로 보자면 옵티마이져가 빠른 실행계획을 만드는데 도움이 되겠죠... 

굳이 따지자면 PK와 유니크키의 차이점을 물어 보시는듯 하는데요..
큰 차이점은 유니크키는 널 값을 허용 하는 겁니다. 키가 될 수 있는 후보 키가 유니크키고 그중 가장 값을 유일하게 구별해 주는 넘을 PK라고 이해하시면 될듯 합니다. 

PK없이 유니크인덱스로만 구성했을때 퍼포먼스가 더 빠르냐는 문제점은 당시 테이블의 데이타의 양 및 어떤 분포도를 가지냐에 따라 사례에 따라 천차 만별 달라집니다. 

튜닝및 퍼포먼스 문제는 언제나 딱 잘라 절대적으로 말할수 없는 문제죠...

2003.12.02

2015년 12월 22일 화요일

[MySQL] INSERT INTO ... DUPLICATE KEY UPDATE & REPLACE INTO

1) REPLACE INTO


REPLACE INTO `TABLE_NAME`
VALUE (col_value1, col_value1, col_value1);

> 데이터 col_value1, col_value2, col_value3를 TABLE에 삽입한다.
중복된 레코드는 삭제 후 삽입한다. (주의! auto_increment 증가함)

mysql> REPLACE INTO test VALUES (1, 'Old', '2014-08-20 18:47:00');
Query OK, 1 row affected (0.04 sec)

mysql> REPLACE INTO test VALUES (1, 'New', '2014-08-20 18:47:42');
Query OK, 2 rows affected (0.04 sec)

mysql> SELECT * FROM test; 
+----+------+---------------------+
| id | data | ts                  |
+----+------+---------------------+
|  1 | New  | 2014-08-20 18:47:42 |
+----+------+---------------------+
1 row in set (0.00 sec)


REPLACE INTO ... SELECT 도 가능하다.

REPLACE INTO `TABLE1`
SELECT col_name1, col_name2, col_name3
FROM `TABLE2`
WHERE where_condition

> TABLE2의 데이터 중 where_condition에 매칭하는 데이터만을 TABLE1에 삽입한다.
중복되면 삭제 후 삽입한다.

주의!

REPLACE를 사용하려면 테이블에 인덱스가 존재하여야 한다.

REPLACE makes sense only if a table has a PRIMARY KEY or UNIQUE index. Otherwise, it becomes equivalent to INSERT, because there is no index to be used to determine whether a new row duplicates another. )

참고 URL:
http://dev.mysql.com/doc/refman/5.7/en/replace.html


2) INSERT INTO ... ON DUPLICATE KEY UPDATE


인덱스에 의해 중복되는 레코드의 삽입을 진행할 경우 INSERT INTO는 에러를 발생시킨다. 하지만 INSERT IN ... ON DUPLICATE KEY UPDATE는 중복이 발생할 경우 이 레코드에 대해 ON DUPLICATE KEY UPDATE 뒤의 조건에 따라 업데이트를 수행한다.

인덱스 중복이 일어난 경우 다음의 두문장은 동일한 역할을 수행한다.

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=c+1;

UPDATE table SET c=c+1 WHERE a=1;

여러 컬럼에 대한 명령의 수행도 가능하며 각 값에 조건에 따른 업데이트도 가능하다.

INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
  ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

위 구문은 아래와 동일한 쿼리이다.

INSERT INTO table (a,b,c) VALUES (1,2,3)
  ON DUPLICATE KEY UPDATE c=3;
INSERT INTO table (a,b,c) VALUES (4,5,6)
  ON DUPLICATE KEY UPDATE c=9;

참고 URL:
http://dev.mysql.com/doc/refman/5.7/en/insert.html
http://dev.mysql.com/doc/refman/5.7/en/insert-select.html
http://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html


PS. 
근래 MySQL에 대한 것을 자주 올리네.. 흠..
내가 어쩌다가 이렇게 된거지;;;; 
DB를 직접 만들어쓰던 내가 어쩌다가 이렇게;; 주르륽.. ㅠㅠ
.

2015년 11월 4일 수요일

MySQL에서의 산술평균/조화평균/기하평균 외 다수

MySQL에서의 산술/조화/기하평균 외 다수

작성자: Robert Eisele

Arithmetic mean

The classical arithmetic mean is already calculable natively as indicated above with the AVG() function or by doing it yourself:
SELECT SUM( x ) / COUNT( x ) FROM t1

Weighted average

A weighted average can be obtained in a similar way by dividing out two sums as follows, where "w" is the per-row weight:
SELECT SUM( x * w ) / SUM( w ) FROM t1

Harmonic average

The harmonic average, which for example is used for rates and ratios can also be calculated quite easily with native functions. Suppose you want to calculate the average cost of data transmission. One hosting packet allows you to run at a rate of 9GiB per dollar and one on 17GiB per dollar. An arithmetic mean would give you an average of 13GiB / dollar, which is wrong. The correct solution would be 2 /(1 / 9 + 1 / 17) = 11.7GiB / dollar, or in abstract MySQL syntax:
SELECT COUNT( x ) / SUM( 1 / x ) FROM t1

Geometric mean

The geometric average, which usually comes into use when it comes to the calculation of product averages, such as tiered discounts or similar quantities, can also be calculated when we introduce some kind of algebra. The product of several numbers can also be defined by the sum of their logarithms, which in turn is taken as the exponent of e. In MySQL syntax that would mean:
SELECT EXP( SUM( LOG( x ) ) ) FROM t1
With this knowledge in mind, we can easily extrapolate from the product to the geomean:
SELECT POW( EXP( SUM( LOG( x ) ) ), 1 / COUNT( x ) ) FROM t1
Which can finally be simplified to:
SELECT EXP( SUM( LOG( x ) ) / COUNT( x ) ) FROM t1

Midrange

The mid-range only takes into account the extremes of a data set and can be computed as follows:
SELECT( MAX( x ) + MIN( x ) ) / 2 FROM t1

Median

There are some good examples in the comments of the documentation of how the median can be implemented with MySQL. However, a spoiled Excel user will run in circles screaming in the face of such cruelties. That's why I've added a median function to my UDF, so that this will be valid:
SELECT median( x ) FROM t1

Most popular value - Mode

For the sake of completeness, I'd like to add the mode, even if this can be determined with the help of native SQL and without too much math:
SELECT x, COUNT( * )
FROM t1
GROUP BY x
ORDER BY COUNT( * ) DESC
LIMIT 1;

Calculating deviations with MySQL

MySQL already provides some functions to identify and classify deviations in data series. In itself, all existing functions are based on the same statistical moment, thus the following relations between the functions can be found:
STDDEV_POP( x ) = STD( x ) = STDDEV( x )

VAR_POP( x ) = VARIANCE( x )

VAR_POP( x ) = STDDEV_POP( x ) * STDDEV_POP( x )

VAR_POP( x ) = VAR_SAMP( x ) *( COUNT( x ) - 1 ) / COUNT( x )

VAR_POP( x ) = SUM( x * x ) / COUNT( x ) - AVG( x ) * AVG( x )

VAR_SAMP( x ) = STDDEV_SAMP( x ) * STDDEV_SAMP( x )

VAR_SAMP( x ) = VAR_POP( x ) /( COUNT( x ) - 1 ) * COUNT( x )

Covariance

Oracle provides the additional functions COVAR_POP(x, y) and COVAR_SAMP(x, y), respectively, in order to calculate the co-variance - the variance between two random variables. With MySQL, this functionality can be simulated with native functions as follows:
COVAR_POP(x, y):
SELECT( SUM( x * y ) - SUM( x ) * SUM( y ) / COUNT( x ) ) / COUNT( x ) FROM t1

COVAR_SAMP(x, y):
SELECT( SUM( x * y ) - SUM( x ) * SUM( y ) / COUNT( x ) ) /( COUNT( x ) - 1 ) FROM t1
This task would be more flawless and efficient with a native function COVARIANCE(x, y), which I've added to my infusion extenseion in order to have a shortcut for the COVAR_POP() example above:
SELECT COVARIANCE( x, y ) FROM t1

Pearson Correlation Coefficient

The covariance function can now be used to calculate the Pearson correlation coefficient. I found a small example of how the correlation is natively implemented in SQL as an indication for the Netflix price. On the other hand, I find the following query looks much better ;)
SELECT COVARIANCE( x, y ) / ( STDDEV( x ) * STDDEV( y ) ) FROM t1

Higher statistical moments

At this point I'd like to mention two other new functions I've intrododuced with my infusion UDF;higher statistical moments, namely the skewness and the kurtosis of a data series:
SELECT SKEWNESS( x ) FROM t1
as well as
SELECT KURTOSIS( x ) FROM t1

Row Ranking

If you want to give each line of a MySQL result a unique serial number, you must use a little trick with variables like this:
SELECT @x:= @x + 1 AS rank, title
FROM t1
JOIN (
   SELECT @x:= 0
)X
ORDER BY weight;
This example may be easy, but it complicates things with more complex queries. I don't know why MySQL doesn't have a function for this, but I've caught it with my infusion extension to correspond to TSQL:
SELECT row_number() AS rank, title FROM t1 ORDER BY weight;

Longtail Analysis

I think it's better to start with an example to illustrate further considerations. With Longtail analysis I mean the representation of a frequency distribution - or a histogram. For search engine optimization you can determine what the search term distribution over a certain period of time was. Since the proportion of unique search terms is usually relatively high and since the image of such a graph is almost always the same, it's obvious to not run GROUP BY queries on a large data set to simply get something like the following:

Looking at the graph, on needs only a few information to approximate it: The number of search queries, the number of unique queries, the number of most searches and the position of the 50% gap. Then you can recreate the image by a cubic function quite well. The only value that we can not calculate with standard tools of MySQL is the 50% limit. To still be able to calculate that, Ive added three new features to the functionality of MySQL: LESSPART(x, part), LESSPARTPCT(x, part%), LESSAVG(x). Let's formulate the query to get the 4 information to draw the graph:
SELECT MAX( x ) Max_X,
   COUNT( x = 1 OR NULL ) Num_1,
   COUNT( x > 1 OR NULL ) Num_X,
   LESSPARTPCT( x, 0.5 ) Border
FROM (
   SELECT COUNT( * ) x
   FROM phrase
   GROUP BY P_ID
) tmp;
Of course, the function LESSPARTPCT can be simulated with native SQL, which is much more complicated with a dynamic result as shown above:
SELECT COUNT( c ) AS LESSPARTPCT
FROM(
   SELECT x, @x:= @x + x, IF(@x < @sum * 0.5, 1, NULL) AS c
   FROM t1
   JOIN(
      SELECT @x:= 0, @count:= 0, @sum:= SUM(rnum)
      FROM t1
   )x
ORDER BY x
)x
Incidentally, the term @x:= @x + x, to get a running sum, can also be simplified with the newly added UDF function RSUMi().

A simple ranking system

As a final example I'd like to introduce the function LESSAVG to build a simple ranking system. The goal is to tell how many may be better or worse than average. As such, we need only 2 Information: How many elements are there in total and how many are smaller than average. This little query is enough to do this:
SELECT count( * ) count, lessavg( x ) less FROM t1;
Based on that you could even customize the output:
if (less / count > 0.5) {

    print less / count * 100, "% are worse than average"

} else {

    print (count - less) / count * 100, "% are better than average"
}
You might also be interested in the following

2015년 11월 3일 화요일

"UNION" 과 "UNION ALL" 의 차이

테이블의 합집합 개념. 즉,
SELECT [COLUMN_NAME] FROM [TABLE1];
SELECT [COLUMN_NAME] FROM [TABLE2];
두개의 테이블을 합한 결과를 보고플때,
SELECT [COLUMN_NAMEFROM [TABLE1];
UNION [ALL]
SELECT [COLUMN_NAMEFROM [TABLE2];
이렇게 사용한다.

여기서 "UNION" "UNION ALL" 은 중복을 배제할 것이냐 허용할 것이냐의 차이이다.

UNION은  중복을 배제한 결과를 주며,
UNION ALL은 중복 안따지고 모든 결과를 나열한다.


2015년 10월 21일 수요일

[PHP] MySQL class in PHP.NET

Heres a easy to use MySQL class for any website

<?php
    class mysql_db {
        //+======================================================+
        function sql_connect($sqlserver, $sqluser, $sqlpassword, $database) {
            $this->connect_id = mysql_connect($sqlserver, $sqluser, $sqlpassword);
            if($this->connect_id) {
                if (mysql_select_db($database)) {
                    return $this->connect_id;
                } else {
                    return $this->error();
                }
            } else {
                return $this->error();
            }
        }
        //+======================================================+
        function error() {
            if(mysql_error() != '') {
                echo '<b>MySQL Error</b>: '.mysql_error().'<br/>';
            }
        }
        //+======================================================+
        function query($query) {
            if ($query != NULL) {
                $this->query_result = mysql_query($query, $this->connect_id);
                if(!$this->query_result) {
                    return $this->error();
                } else {
                    return $this->query_result;
                }
            } else {
                return '<b>MySQL Error</b>: Empty Query!';
            }
        }
        //+======================================================+
        function get_num_rows($query_id = "") {
            if ($query_id == NULL) {
                $return = mysql_num_rows($this->query_result); 
            } else {
                $return = mysql_num_rows($query_id);
            }
            if (!$return) {
                $this->error();
            } else {
                return $return;
            }
        }
        //+======================================================+
        function fetch_row($query_id = ""){
            if($query_id == NULL){
                $return = mysql_fetch_array($this->query_result); 
            }else{
                $return = mysql_fetch_array($query_id);
            }
            if(!$return){
                $this->error();
            }else{
                return $return;
            }
        }    
        //+======================================================+
        function get_affected_rows($query_id = "") {
            if($query_id == NULL) {
                $return = mysql_affected_rows($this->query_result); 
            } else {
                $return = mysql_affected_rows($query_id);
            }
            if(!$return) {
                $this->error();
            } else {
                return $return;
            }
        }
        //+======================================================+
        function sql_close(){
            if($this->connect_id){
                return mysql_close($this->connect_id);
            }
        }
        //+======================================================+    
    }
    /* Example */
    $DB = new mysql_db();
    $DB->sql_connect('sql_host', 'sql_user', 'sql_password', 'sql_database_name');
    $DB->query("SELECT * FROM `members`");
    $DB->sql_close();
?>




2015년 9월 9일 수요일

[번개장터] 실무자가 전하는 MySQL 쿨팁

번개장터에서 MySQL 사용하면서 알게된 것들

지난 3년간 번개장터 서비스를 운영하면서 얻은 MySQL 운영 팁을 알려드립니다.

원문출처: 번개장터 Quicket Engineering


2015년 9월 8일 화요일

[MySQL] 인덱스 생성, 조회

출처: albumbang

인덱스 만들기

1. 추가하여 만들기

CREATE INDEX <Index name> ON <Table name> ( column 1column 2, ... );

2. 테이블 생성시 만들기

끝에....

INDEX <Index name> ( column 1, column 2 )
UNIQUE INDEX <Index name> ( column ) --> 항상 유일해야 함.

3. 이렇게도 생성한다

ALTER TABLE <Table name> ADD INDEX <Index name> ( column 1, column 2, ... );

4. 인덱스 보기

SHOW INDEX FROM <Table name>;


5. 인덱스 삭제

ALTER TABLE <Table name> DROP INDEX <Index name>;

2015년 8월 4일 화요일

C에서 MySQL연결 시 한글(UTF-8)깨짐문제 해결

mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_options(&mysql, MYSQL_INIT_COMMAND, "SET NAMES utf8");
mysql_real_connect(&mysql,T_SERVER, T_USER, T_PASSWD, T_DBNM,0,0,0);






2015년 6월 8일 월요일

[Linux] DNS, MySQL, Apache 프로세스 실행/종료/재시작 (2006)

(2006/12/11 19:02 작성)

출처: http://blog.naver.com/paolo2000/100015751382

DNS 서버


(1) 시작

[root@test root]# /etc/rc.d/init.d/named start

(2) 재시작

[root@test root]# /etc/rc.d/init.d/named reload

(3) 정지

[root@test root]# /etc/rc.d/init.d/named stop

이렇게 되면서 정지가 되지 않았습니다.

[root@test root]# ps -ef | grep named
named 17585 1 0 22:39 ? 00:00:00 [named]
root 17728 17314 0 22:42 pts/2 00:00:00 grep named

bind 는 아래 명령어를 사용해서 정지 시킬 수 있으나 먹지 않더군요(권장사항인데...)

[root@test root]# rndc stop

그래서 할 수 없이 깔끔하게 프로세스를 죽였입니다.

[root@test root]# killall named
[root@test root]# ps -ef | grep named


Apache & Mysql

(1) mysql 및 apache 시작

- mysql 시작 :
/usr/local/mysql/bin/mysqld_safe &

- apache 시작 :
/usr/local/apache/bin/apachectl start


(2) mysql 및 apache 재 시작

- mysql 재시작 :
/usr/local/mysql/bin/mysqladmin -u root -p reload

→ 이 방법은 완벽한 재 시작이 아닙니다. 문제가 발생시 완전히 중지시키고 다시 시작하세요.

- apache 재시작 :
/usr/local/apache/bin/apachectl restart


(3) mysql 및 apache 중지

- mysql 중지 :
/usr/local/mysql/bin/mysqladmin -u root -p shutdown

→ 이 방법으로 죽지 않을 때는 killall mysqld 라고 하면 죽습니다.

- apache 중지 :
/usr/local/apache/bin/apachectl stop

→ 대부분 이 방법으로 죽으나 죽지 않는다면, killall httpd 하시면 죽습니다.




2015년 6월 5일 금요일

MySQL - Commands out of sync; you can't run this command now

예를들어….
memset(query, 0x00, QUERYSIZ);
sprintf(query, “DROP PROCEDURE IF EXISTS mytable; CREATE TABLE IF NOT EXISTS mytable ( Term VARCHAR(255) NOT NULL, KeyNo int DEFAULT 0, UNIQUE (Term)););
state1 = mysql_query(conn, query);

memset(query, 0x00, QUERYSIZ);
sprintf(query, "SELECT * FROM mytable ( 생략... );");
state2 = mysql_query(conn, query);

이런쿼리를 실행했다. 헌데 두번째 쿼리서..
Commands out of sync; you can’t run this command now

위와 같은 에러가 보였다. 뭐지?! 이 에러는 쿼리 실행 후 resource가 발생하였는데 이를 mysql_free_result() 나 mysql_use_result()등으로 처리없이 막바로 다른 실행을 진행하였을 때 발생한다.

mysql_query()는 SELECT, SHOW, DESCRIBE, EXPLAIN, 결과셋을 반환하는 기타 구문에서 성공시 resource를, 오류시 FALSE를 반환한다. 또한 다른 형식의 SQL 구문, 즉, INSERT, UPDATE, DELETE, DROP 등에서는 성공하면 TRUE를, 실패하면FALSE를 반환한다.

따라서 DROP과 CREATE를 실행한 위 구문은 문제가 없다고 생각했다. 헌데..

https://dev.mysql.com/doc/refman/5.0/en/commands-out-of-sync.html

B.5.2.14 Commands out of sync
If you get Commands out of sync; you can't run this command nowin your client code, you are calling client functions in the wrong order.
This can happen, for example, if you are using mysql_use_result() and try to execute a new query before you have called mysql_free_result(). It can also happen if you try to execute two queries that return data without calling mysql_use_result() or mysql_store_result()in between.

라고하더라;;;;

두개의 쿼리(멀티쿼리)를 동시 질의한 경우에도 마찬가지라는 소리다.
그러면, CLIENT_MULTI_STATEMENTS 옵션은 당췌 무슨소용인가?!?!

물론 위의 쿼리를 두개로 분할하여 질의하면 문제는 사라진다. 하지만 멀티쿼리를 꼭 써야하는 경우, 이 문제를 어떻게 풀어야 할까?


아 궁금하다;;;;;;;;;;;;


2015년 6월 3일 수요일

MySQL DB connection Sample (2009)

(2009/05/16 00:10 작성)

#define DB_IP "127.0.0.1"
#define DB_USER "root"
#define DB_PASSWD "12345"
#define DB_NAME "mydb"
#define DB_PORT 3306

// DB CONNECT PART ///////////////////////////////////////////////////////////////////////////
void db_disconnect(MYSQL *db)
{
  if (db) mysql_close(db);
}
MYSQL *db_connect(MYSQL *db, char *serverIP)
{
  db = mysql_init(db);
  //fprintf(stderr, "[connect: %s]\n", serverIP);
  if(!mysql_real_connect(db, DB_IP, DB_USER, DB_PASSWD, DB_NAME, DB_PORT, 
      NULL, CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS)) {
    db_disconnect(db);
  }
  return (db);
}
// DB CONNECT PART ///////////////////////////////////////////////////////////////////////////