子查询中的MySQL regexp

时间:2011-03-01 19:36:24

标签: mysql regex subquery

我有一个非常特别的问题,在查看了许多资源后,我无法找到解决问题的方法。

我正在运行的MySQL版本是MySQL 5.0.91

鉴于以下表格定义:

DROP TABLE IF EXISTS `item`;
CREATE TABLE `item` (
  `id` int(11) NOT NULL default '0',
  `code` varchar(4096) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records 
-- ----------------------------
INSERT INTO `item` VALUES ('1', 'pizza|large|pepp');
INSERT INTO `item` VALUES ('3', 'pizza|medium|pepp');
INSERT INTO `item` VALUES ('2', 'pizza|small|pepp');
INSERT INTO `item` VALUES ('4', 'appetizer|fries|large');
INSERT INTO `item` VALUES ('5', 'beverage|2_liter|pepsi');
INSERT INTO `item` VALUES ('6', 'pizza|small|cheese');

DROP TABLE IF EXISTS `item_regexp`;
CREATE TABLE `item_regexp` (
  `id` int(11) NOT NULL default '0',
  `regexp` varchar(4096) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records 
-- ----------------------------
INSERT INTO `item_regexp` VALUES ('1', '((pizza)\\\\|)((large|medium)\\\\|)');
INSERT INTO `item_regexp` VALUES ('2', '((pizza)\\\\|)((.*)\\\\|)((alldressed))');
INSERT INTO `item_regexp` VALUES ('3', '((beverage)\\\\|)((2_liter)\\\\|)');
INSERT INTO `item_regexp` VALUES ('4', '((pizza)\\\\|)((.*)\\\\|)((pepp))');

总之,表项表示发票上的项目。在我的例子中,我有5个项目。代码是该特定项的内部表示。

然后,item_regexp表用于指定可能的产品。例如,这可用于捕获满足给定代码模式的所有可能产品以应用折扣等。

我想加载所有item_regexp条目,其中每个条目的数量都可以从发票上的项目列表中捕获。

使用子查询来计算表item中由我的正则表达式捕获的条目数,这给了我一个正确的结果:

################
# QUERY #1     #
################
SELECT 
(SELECT
count(*)
FROM
item
where 
`item`.`code` REGEXP '((pizza)\\|)((large|medium)\\|)') as "regexp1 count"
,
(SELECT
count(*)
FROM
item
where 
`item`.`code` REGEXP '((pizza)\\|)((.*)\\|)((alldressed))') as "regexp2 count"
,
(SELECT
count(*)
FROM
item
where 
`item`.`code` REGEXP '((beverage)\\|)((2_liter)\\|)') as "regexp3 count" 
,
(SELECT
count(*)
FROM
item
where 
`item`.`code` REGEXP '((pizza)\\|)((.*)\\|)((pepp))') as "regexp4 count" ;
+---------------+---------------+---------------+---------------+
| regexp1 count | regexp2 count | regexp3 count | regexp4 count |
+---------------+---------------+---------------+---------------+
|             2 |             0 |             1 |             3 |
+---------------+---------------+---------------+---------------+
1 row in set

但是,在更通用的查询中将其作为子查询运行似乎总是将0作为计数。这就好像正则表达式没有工作或没有考虑在内。

################
# QUERY #2     #
################
SELECT 
`item_regexp`.`regexp`
, 
(
SELECT
count(*)
FROM
item
where 
`item`.`code` REGEXP `item_regexp`.`regexp`
) as "regexp_count"
FROM 
item_regexp ;
+-------------------------------------+--------------+
| regexp                              | regexp_count |
+-------------------------------------+--------------+
| ((pizza)\\|)((large|medium)\\|)     |            0 |
| ((pizza)\\|)((.*)\\|)((alldressed)) |            0 |
| ((beverage)\\|)((2_liter)\\|)       |            0 |
| ((pizza)\\|)((.*)\\|)((pepp))       |            0 |
+-------------------------------------+--------------+
4 rows in set

有什么我错过了这个过程,以便QUERY#2产生与QUERY#1相同的计数值吗?

感谢您的帮助。

迈克

1 个答案:

答案 0 :(得分:0)

这是因为当您定义文字

((beverage)\\|)((2_liter)\\|)

REGEXP将双\视为单个。 当你把它放在一个列中时,它们是双倍的,所以它等同于文字

((beverage)\\\\|)((2_liter)\\\\|)

这使他们与众不同。你使用文字是正确的,但你插入item_regexp是错误的。请尝试以下

delete from `item_regexp`;
INSERT INTO `item_regexp` VALUES ('1', '((pizza)\\|)((large|medium)\\|)');
INSERT INTO `item_regexp` VALUES ('2', '((pizza)\\|)((.*)\\|)((alldressed))');
INSERT INTO `item_regexp` VALUES ('3', '((beverage)\\|)((2_liter)\\|)');
INSERT INTO `item_regexp` VALUES ('4', '((pizza)\\|)((.*)\\|)((pepp))');