Saturday, December 27, 2014

查找/從字符串中解析字符串

Original post: http://anothermysqldba.blogspot.com/2014/12/findparse-string-from-within-string.html

所以,我注意到了一些不同的問題,並張貼關於解析字符串了另一個字符串最近。 雖然一些解決方案包括創建新的功能等也可以在某些情況下,一個單一的查詢內完成。 

例如,讓我們說,我們正在尋找拉出從URL域。 我會盡量細講,為什麼和如何工作的。 
我們有如下表。 

CREATE TABLE `parse_example` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`urldemo` varchar(150) NOT NULL, 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 
+----+----------------------------+ 
| id | urldemo | 
+----+----------------------------+ 
| 1 | http://www.mysql.com/ | 
| 2 | http://www.percona.com/ | 
| 3 | https://tools.percona.com/ | 
| 4 | https://mariadb.com/ | 
| 5 | http://planet.mysql.com/ | 
| 6 | http://dev.mysql.com/doc/ | 
+----+----------------------------+ 


這個例子的目的是無視http://或https://開頭和任何的.COM之後。 所以我們用locate找到位置。 

在.COM引用是容易的,因為那是恆定的,所以我們可以與啟動。 

SELECT LOCATE('.com', urldemo), urldemo FROM parse_example; 
+-------------------------+----------------------------+ 
| LOCATE('.com', urldemo) | urldemo | 
+-------------------------+----------------------------+ 
| 17 | http://www.mysql.com/ | 
| 19 | http://www.percona.com/ | 
| 22 | https://tools.percona.com/ | 
| 16 | https://mariadb.com/ | 
| 20 | http://planet.mysql.com/ | 
| 17 | http://dev.mysql.com/doc/ | 
+-------------------------+----------------------------+ 


OK,所以我們要刪除的/,什麼地方是什麼? 

SELECT LOCATE('.com', urldemo) as start, LOCATE('.com', urldemo) +4 as end, SUBSTRING(urldemo FROM LOCATE('.com', urldemo) + 4 ) AS resulting , urldemo FROM parse_example; 
+-------+-----+-----------+----------------------------+ 
| start | end | resulting | urldemo | 
+-------+-----+-----------+----------------------------+ 
| 17 | 21 | / | http://www.mysql.com/ | 
| 19 | 23 | / | http://www.percona.com/ | 
| 22 | 26 | / | https://tools.percona.com/ | 
| 16 | 20 | / | https://mariadb.com/ | 
| 20 | 24 | / | http://planet.mysql.com/ | 
| 17 | 21 | /doc/ | http://dev.mysql.com/doc/ | 
+-------+-----+-----------+----------------------------+

這給了我們我們的最終位置,我只把現場別名使結果更容易執行。 

現在,經過HTTP和HTTPS整理其實是很容易的,以及它們都具有://之後他們,所以我們只需要第二的位置/字符串中。 


SELECT LOCATE('/', urldemo) as first, LOCATE('/', urldemo) +1 as second, urldemo 
FROM parse_example; 
+-------+--------+----------------------------+ 
| first | second | urldemo | 
+-------+--------+----------------------------+ 
| 6 | 7 | http://www.mysql.com/ | 
| 6 | 7 | http://www.percona.com/ | 
| 7 | 8 | https://tools.percona.com/ | 
| 7 | 8 | https://mariadb.com/ | 
| 6 | 7 | http://planet.mysql.com/ | 
| 6 | 7 | http://dev.mysql.com/doc/ | 
+-------+--------+----------------------------+ 


這些查詢只是顯示了最終的查詢的不同方面會做。 因此,讓我們把它放在一起。 


SELECT 
TRIM(TRAILING SUBSTRING(urldemo FROM LOCATE('.com', urldemo) + 4 ) 
FROM SUBSTRING(urldemo FROM LOCATE('/', urldemo) + 2 ) ) AS parsed_domain , 
urldemo as original_url 
FROM parse_example; 
+-------------------+----------------------------+ 
| parsed_domain | original_url | 
+-------------------+----------------------------+ 
| www.mysql.com | http://www.mysql.com/ | 
| www.percona.com | http://www.percona.com/ | 
| tools.percona.com | https://tools.percona.com/ | 
| mariadb.com | https://mariadb.com/ | 
| planet.mysql.com | http://planet.mysql.com/ | 
| dev.mysql.com | http://dev.mysql.com/doc/ | 
+-------------------+----------------------------+ 


現在,希望可以幫助您能夠解析出任何你需要的。 本實施例被限制在一個網址。 但是,由於功能的一些例子已經在這裡是我的,你可以用它來解析任何你需要的功能的例子。 



CREATE FUNCTION PARSE_STRING(delimiterA VARCHAR(50), delimiterB VARCHAR(50), passed_string VARCHAR(255) ) 
RETURNS VARCHAR(255) DETERMINISTIC 
RETURN 
TRIM(TRAILING SUBSTRING(passed_string FROM LOCATE(delimiterB, passed_string) ) 
FROM SUBSTRING(passed_string FROM LOCATE(delimiterA, passed_string) + CHAR_LENGTH(delimiterA) ) ) ; 

SELECT PARSE_STRING('//','.com', urldemo) FROM parse_example; 
+------------------------------------+ 
| PARSE_STRING('//','.com', urldemo) | 
+------------------------------------+ 
| www.mysql | 
| www.percona | 
| tools.percona | 
| mariadb | 
| planet.mysql | 
| dev.mysql | 
+------------------------------------+ 


從全名外地拉一個姓氏: 

SELECT PARSE_STRING('John ','', 'John Smith') ; 
+----------------------------------------+ 
| PARSE_STRING('John ','', 'John Smith') | 
+----------------------------------------+ 
| Smith | 
+----------------------------------------+ 


拉頭名 

SELECT PARSE_STRING('',' Smith', 'John Smith') ; 
+-----------------------------------------+ 
| PARSE_STRING('',' Smith', 'John Smith') | 
+-----------------------------------------+ 
| John | 
+-----------------------------------------+ 


授予的名稱例子,你需要知道的分隔符值。 但是,這只是一個例子,你可以建立在。

Friday, December 19, 2014

一個MySQL分區和SUBPARTITION示例

Original post: http://anothermysqldba.blogspot.com/2014/12/a-mysql-partition-and-subpartition.html

因此,這是一個如何建立一個分區和MySQL的一個SUBPARTITION只是一個簡單的例子。 這裡的概念是,你必須在一個時間字段無數值表中的數據。 你可能有分佈在很多年(最有可能的,你做的)數據。 所以這個分區數據的一種方法是通過一年來排序,但隨後也即每年分區內按月份排序。 

以下是你可以用考慮一個例子。 

考慮到測試表。 你的表當然有更多的領域。 

CREATE TABLE `t1` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`date_time` datetime DEFAULT NOW(), 
PRIMARY KEY (`id`) 
) ENGINE=InnoDB; 


首先,我將填充測試表隨機值的DATE_TIME領域。 

delimiter // 
CREATE PROCEDURE populate_t1( IN rowsofdata INT ) 
BEGIN 

SET @A = 1; 
SET @B = 25 - @A; 

WHILE rowsofdata > 0 DO 
SELECT FLOOR( @A + (RAND() * @B )) INTO @randvalue; 
INSERT INTO t1 
SELECT NULL, NOW() - INTERVAL @randvalue MONTH; 
SET rowsofdata = rowsofdata - 1; 
END WHILE; 
END// 
delimiter ; 
call populate_t1(1000); 


檢查,看看我結束了什麼樣的價值觀為: 

> SELECT COUNT(*) FROM t1 WHERE date_time BETWEEN '2012-01-01 00:00:00' AND '2013-01-01 00:00:00'\G 
*************************** 1. row *************************** 
COUNT(*): 43 
1 row in set (0.00 sec) 

> SELECT COUNT(*) FROM t1 WHERE date_time BETWEEN '2013-01-01 00:00:00' AND '2014-01-01 00:00:00'\G 
*************************** 1. row *************************** 
COUNT(*): 529 
1 row in set (0.00 sec) 

> SELECT COUNT(*) FROM t1 WHERE date_time BETWEEN '2014-01-01 00:00:00' AND NOW() \G
*************************** 1. row *************************** 
COUNT(*): 428 
1 row in set (0.00 sec) 


現在,我可以改變表,所以我可以通過分區添加我的分區,然後測試值計數。 

ALTER TABLE t1 DROP PRIMARY KEY, ADD PRIMARY KEY (`id`,`date_time`), LOCK=SHARED; 
ALTER TABLE t1 
PARTITION BY RANGE( YEAR(date_time) ) 
SUBPARTITION BY HASH(MONTH(date_time) ) ( 

PARTITION p2012 VALUES LESS THAN (2013) ( 
SUBPARTITION dec_2012, 
SUBPARTITION jan_2012, 
SUBPARTITION feb_2012, 
SUBPARTITION mar_2012, 
SUBPARTITION apr_2012, 
SUBPARTITION may_2012, 
SUBPARTITION jun_2012, 
SUBPARTITION jul_2012, 
SUBPARTITION aug_2012, 
SUBPARTITION sep_2012, 
SUBPARTITION oct_2012, 
SUBPARTITION nov_2012 
), 

PARTITION p2013 VALUES LESS THAN (2014) ( 
SUBPARTITION dec_2013, 
SUBPARTITION jan_2013, 
SUBPARTITION feb_2013, 
SUBPARTITION mar_2013, 
SUBPARTITION apr_2013, 
SUBPARTITION may_2013, 
SUBPARTITION jun_2013, 
SUBPARTITION jul_2013, 
SUBPARTITION aug_2013, 
SUBPARTITION sep_2013, 
SUBPARTITION oct_2013, 
SUBPARTITION nov_2013 

), 
PARTITION p2014 VALUES LESS THAN (2015) ( 
SUBPARTITION dec_2014, 
SUBPARTITION jan_2014, 
SUBPARTITION feb_2014, 
SUBPARTITION mar_2014, 
SUBPARTITION apr_2014, 
SUBPARTITION may_2014, 
SUBPARTITION jun_2014, 
SUBPARTITION jul_2014, 
SUBPARTITION aug_2014, 
SUBPARTITION sep_2014, 
SUBPARTITION oct_2014, 
SUBPARTITION nov_2014 
), 

PARTITION pmax VALUES LESS THAN MAXVALUE ( 
SUBPARTITION dec_max, 
SUBPARTITION jan_max, 
SUBPARTITION feb_max, 
SUBPARTITION mar_max, 
SUBPARTITION apr_max, 
SUBPARTITION may_max, 
SUBPARTITION jun_max, 
SUBPARTITION jul_max, 
SUBPARTITION aug_max, 
SUBPARTITION sep_max, 
SUBPARTITION oct_max, 
SUBPARTITION nov_max 
) 
); 


我型我秀創建表非常不同了。 

> show create table t1; 
CREATE TABLE `t1` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`date_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, 
PRIMARY KEY (`id`,`date_time`) 
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=latin1 
/*!50100 PARTITION BY RANGE ( YEAR(date_time)) 
SUBPARTITION BY HASH (MONTH(date_time)) 
(PARTITION p2012 VALUES LESS THAN (2013) 
(SUBPARTITION dec_2012 ENGINE = InnoDB, 
SUBPARTITION jan_2012 ENGINE = InnoDB, 
SUBPARTITION feb_2012 ENGINE = InnoDB, 
SUBPARTITION mar_2012 ENGINE = InnoDB, 
SUBPARTITION apr_2012 ENGINE = InnoDB, 
SUBPARTITION may_2012 ENGINE = InnoDB, 
SUBPARTITION jun_2012 ENGINE = InnoDB, 
SUBPARTITION jul_2012 ENGINE = InnoDB, 
SUBPARTITION aug_2012 ENGINE = InnoDB, 
SUBPARTITION sep_2012 ENGINE = InnoDB, 
SUBPARTITION oct_2012 ENGINE = InnoDB, 
SUBPARTITION nov_2012 ENGINE = InnoDB), 
PARTITION p2013 VALUES LESS THAN (2014) 
(SUBPARTITION dec_2013 ENGINE = InnoDB, 
SUBPARTITION jan_2013 ENGINE = InnoDB, 
SUBPARTITION feb_2013 ENGINE = InnoDB, 
SUBPARTITION mar_2013 ENGINE = InnoDB, 
SUBPARTITION apr_2013 ENGINE = InnoDB, 
SUBPARTITION may_2013 ENGINE = InnoDB, 
SUBPARTITION jun_2013 ENGINE = InnoDB, 
SUBPARTITION jul_2013 ENGINE = InnoDB, 
SUBPARTITION aug_2013 ENGINE = InnoDB, 
SUBPARTITION sep_2013 ENGINE = InnoDB, 
SUBPARTITION oct_2013 ENGINE = InnoDB, 
SUBPARTITION nov_2013 ENGINE = InnoDB), 
PARTITION p2014 VALUES LESS THAN (2015) 
(SUBPARTITION dec_2014 ENGINE = InnoDB, 
SUBPARTITION jan_2014 ENGINE = InnoDB, 
SUBPARTITION feb_2014 ENGINE = InnoDB, 
SUBPARTITION mar_2014 ENGINE = InnoDB, 
SUBPARTITION apr_2014 ENGINE = InnoDB, 
SUBPARTITION may_2014 ENGINE = InnoDB, 
SUBPARTITION jun_2014 ENGINE = InnoDB, 
SUBPARTITION jul_2014 ENGINE = InnoDB, 
SUBPARTITION aug_2014 ENGINE = InnoDB, 
SUBPARTITION sep_2014 ENGINE = InnoDB, 
SUBPARTITION oct_2014 ENGINE = InnoDB, 
SUBPARTITION nov_2014 ENGINE = InnoDB), 
PARTITION pmax VALUES LESS THAN MAXVALUE 
(SUBPARTITION dec_max ENGINE = InnoDB, 
SUBPARTITION jan_max ENGINE = InnoDB, 
SUBPARTITION feb_max ENGINE = InnoDB, 
SUBPARTITION mar_max ENGINE = InnoDB, 
SUBPARTITION apr_max ENGINE = InnoDB, 
SUBPARTITION may_max ENGINE = InnoDB, 
SUBPARTITION jun_max ENGINE = InnoDB, 
SUBPARTITION jul_max ENGINE = InnoDB, 
SUBPARTITION aug_max ENGINE = InnoDB, 
SUBPARTITION sep_max ENGINE = InnoDB, 
SUBPARTITION oct_max ENGINE = InnoDB, 
SUBPARTITION nov_max ENGINE = InnoDB)) 


所以,我們還能指望我們的價值預期? 

> SELECT count(*) FROM t1 PARTITION (p2012) \G 
*************************** 1. row *************************** 
count(*): 43 
> SELECT count(*) FROM t1 PARTITION (p2013) \G 
*************************** 1. row *************************** 
count(*): 529 
> SELECT count(*) FROM t1 PARTITION (p2014) \G 
*************************** 1. row *************************** 
count(*): 428 


到目前為止好,所有的價值觀匹配了我們所收到的數量。 所以我們也可以算或每子分區中進行選擇。 


> SELECT * FROM t1 PARTITION (dec_2012) limit 5; 
+-----+---------------------+ 
| id | date_time | 
+-----+---------------------+ 
| 59 | 2012-12-19 00:59:57 | 
| 68 | 2012-12-19 00:59:58 | 
| 93 | 2012-12-19 00:59:59 | 
| 105 | 2012-12-19 00:59:59 | 
| 111 | 2012-12-19 00:59:59 | 
+-----+---------------------+ 

> SELECT * FROM t1 PARTITION (jan_2013) limit 5; 
+-----+---------------------+ 
| id | date_time | 
+-----+---------------------+ 
| 6 | 2013-01-19 00:59:55 | 
| 29 | 2013-01-19 00:59:56 | 
| 55 | 2013-01-19 00:59:57 | 
| 79 | 2013-01-19 00:59:58 | 
| 100 | 2013-01-19 00:59:59 | 
+-----+---------------------+ 

> SELECT * FROM t1 PARTITION (jan_2014) limit 5; 
+-----+---------------------+ 
| id | date_time | 
+-----+---------------------+ 
| 16 | 2014-01-19 00:59:55 | 
| 190 | 2014-01-19 01:00:04 | 
| 191 | 2014-01-19 01:00:04 | 
| 229 | 2014-01-19 01:00:05 | 
| 234 | 2014-01-19 01:00:06 | 
+-----+---------------------+ 

> SELECT * FROM t1 PARTITION (jun_2014) limit 5; 
+-----+---------------------+ 
| id | date_time | 
+-----+---------------------+ 
| 13 | 2014-06-19 00:59:55 | 
| 189 | 2014-06-19 01:00:04 | 
| 221 | 2014-06-19 01:00:05 | 
| 222 | 2014-06-19 01:00:05 | 
| 238 | 2014-06-19 01:00:06 | 
+-----+---------------------+ 

> SELECT * FROM t1 PARTITION (dec_2013) limit 5; 
+-----+---------------------+ 
| id | date_time | 
+-----+---------------------+ 
| 50 | 2013-12-19 00:59:57 | 
| 74 | 2013-12-19 00:59:58 | 
| 98 | 2013-12-19 00:59:59 | 
| 107 | 2013-12-19 00:59:59 | 
| 167 | 2013-12-19 01:00:02 | 
+-----+---------------------+ 


這是偉大的,方便的,但是,當2015年或2016年左右出現什麼情況? 所有這些數據將在PMAX分區。 那麼,我們如何P2014和Pmax的在增加一個新的分區? 

如果您在PMAX沒有數據,你可以刪除它並添加一個新的分區到年底。 但它也很容易重新組織的分區。 這將需要的PMAX分區,改變成我們新的分區。 


ALTER TABLE t1 REORGANIZE PARTITION pmax INTO ( 
PARTITION p2015 VALUES LESS THAN (2016) ( 
SUBPARTITION dec_2015, 
SUBPARTITION jan_2015, 
SUBPARTITION feb_2015, 
SUBPARTITION mar_2015, 
SUBPARTITION apr_2015, 
SUBPARTITION may_2015, 
SUBPARTITION jun_2015, 
SUBPARTITION jul_2015, 
SUBPARTITION aug_2015, 
SUBPARTITION sep_2015, 
SUBPARTITION oct_2015, 
SUBPARTITION nov_2015 
), 
PARTITION pmax VALUES LESS THAN MAXVALUE ( 
SUBPARTITION dec_max, 
SUBPARTITION jan_max, 
SUBPARTITION feb_max, 
SUBPARTITION mar_max, 
SUBPARTITION apr_max, 
SUBPARTITION may_max, 
SUBPARTITION jun_max, 
SUBPARTITION jul_max, 
SUBPARTITION aug_max, 
SUBPARTITION sep_max, 
SUBPARTITION oct_max, 
SUBPARTITION nov_max 
) 
); 


希望這可以幫助,好運。