【发布时间】:2016-10-18 20:23:28
【问题描述】:
我正在尝试解决 WHERE 子查询或寻找不同的解决方案。 我想要实现的是基于这个查询:
SELECT c.orig_point_id,
(SELECT attempts
FROM
(SELECT
orig_carrier_id,
orig_point_id,
term_point_id,
term_route,
currency_sell,
is_special,
COUNT(*) AS attempts
FROM cdr
WHERE 1=1
AND start_time >= '2016-10-01 0:00:00'
AND start_time <= '2016-10-31 23:59:59'
GROUP BY orig_carrier_id, currency_sell) AS c0
WHERE c0.orig_carrier_id=3
AND c0.currency_sell="USD"
LIMIT 1) AS attempts,
(SELECT SPLIT(clear_number) as array
FROM
(SELECT
COUNT(*) as total,
clear_number,
orig_carrier_id,
currency_sell
FROM `cdr`
WHERE `start_time`>='2016-10-01 00:00:00'
AND start_time <= '2016-10-31 23:59:59'
GROUP BY `clear_number`
ORDER BY total DESC) AS c0
WHERE c0.orig_carrier_id=3
AND c0.currency_sell="USD"
LIMIT 1) AS splitted_number
FROM cdr AS c
GROUP BY c.orig_carrier_id, c.currency_sell;
SPLIT 是一个函数。该部分中的查询找到一个数字(最频繁),然后函数将其拆分为 ex。 12345,1234,123,12,1。当我尝试将其用作 IN 子查询时,问题就来了。直接使用时,mysql 表示不支持功能。看起来查询太复杂了。 当我将子查询别名为解决方法时,它返回 NULL,因此解决方法不起作用,我相信它返回 NULL 的原因与它不可行的原因相同。
SELECT
CONCAT_WS(" - ",country,region) AS route_name
FROM numbering_plan_external
WHERE
prefix IN(
SELECT array
FROM
(SELECT SPLIT(clear_number) as array
FROM
(SELECT
COUNT(*) as total,
clear_number,
orig_carrier_id,
currency_sell
FROM `cdr`
WHERE `start_time`>='2016-10-01 00:00:00'
AND start_time <= '2016-10-31 23:59:59'
GROUP BY `clear_number`
ORDER BY total DESC) AS c0
WHERE c0.orig_carrier_id=3
AND c0.currency_sell="USD"
LIMIT 1) AS splitted_number)
ORDER BY prefix DESC LIMIT 1) AS top_route
我在这里做错了什么,还是有不同的方法来实现这一点。我可以只留下拆分号码,然后通过 PHP 找到路线。根据结果,这将需要大量查询,如果可能,我会尽量避免。
提前谢谢各位。
一些样本数据
CREATE TABLE IF NOT EXISTS `numbering_plan_external` (
`id` int(11) NOT NULL,
`country` varchar(255) NOT NULL,
`region` varchar(255) DEFAULT NULL,
`prefix` varchar(50) NOT NULL,
`is_mobile` tinyint(1) NOT NULL DEFAULT '0',
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`min_sale_price_currency` char(3) CHARACTER SET latin1 COLLATE latin1_general_ci DEFAULT NULL,
`min_sale_price_amount` decimal(10,4) DEFAULT NULL
) ENGINE=InnoDB AUTO_INCREMENT=14004 DEFAULT CHARSET=latin1;
INSERT INTO `numbering_plan_external`
(`id`, `country`, `region`,`prefix`, `is_mobile`, `last_updated`, `min_sale_price_currency`, `min_sale_price_amount`)
VALUES
(13047, 'Tunisia', '', '216', 0, '2016-02-17 12:30:44', NULL, NULL),
(13048, 'Tunisia', 'Mobile (ORANGE)', '2165', 1, '2016-02-17 12:30:44', NULL, NULL),
(13049, 'Tunisia', 'Mobile (ORASCOM)', '2162', 1, '2016-02-17 12:30:44', NULL, NULL),
(13050, 'Tunisia', 'Mobile (TUNTEL)', '21640', 1, '2016-02-17 12:30:44', NULL, NULL),
(13051, 'Tunisia', 'Mobile (TUNTEL)', '21641', 1, '2016-02-17 12:30:44', NULL, NULL),
(13052, 'Tunisia', 'Mobile (TUNTEL)', '2169', 1, '2016-02-17 12:30:44', NULL, NULL);
CREATE TABLE IF NOT EXISTS `cdr` (
`id` int(11) NOT NULL,
`orig_carrier_id` int(11) NOT NULL,
`orig_point_id` int(11) NOT NULL,
`term_carrier_id` int(11) NOT NULL,
`term_point_id` int(11) NOT NULL,
`clear_number` varchar(100) COLLATE latin1_general_ci NOT NULL,
`is_special` tinyint(1) NOT NULL DEFAULT '0',
`start_time` datetime NOT NULL,
`currency_sell` char(3) COLLATE latin1_general_ci NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=16385 DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;
INSERT INTO `cdr`
(`id`, `orig_carrier_id`, `orig_point_id`, `term_carrier_id`, `term_point_id`, `clear_number`, `is_special`, `start_time`, `currency_sell`) VALUES
(1, 3, 5, 0, 0, '21658502507', 0, '2016-10-17 00:02:04', 'USD'),
(2, 3, 5, 0, 0, '21658502507', 0, '2016-10-17 00:02:04', 'USD'),
(3, 3, 5, 0, 0, '21658502507', 0, '2016-10-17 00:03:56', 'USD'),
(4, 3, 5, 0, 0, '21658502507', 0, '2016-10-17 00:09:28', 'USD'),
(5, 3, 5, 0, 0, '21658502507', 0, '2016-10-17 00:16:35', 'USD');
【问题讨论】:
-
如果您提供示例数据(作为我们可以重复使用的插入或文本)以及预期结果,我们可以提出更好的解决方案。 (样本不必很大!)
-
添加了一些示例数据。
-
表
numbering_plan_external的相关性是什么?我在查询中看到的只是cdr。您还可以解释您期望从该数据查询的结果是什么,这将是有益的。例如现在(根据该数据)我认为没有理由使用拆分功能。 -
@Used_By_Already
numbering plan externaltable 的相关性可以在第二个子查询中找到。它以 `SELECT CONCAT_WS(" - ",country,region) AS route_name ... 21658502507,SPLIT 将生成一个相同号码的列表,最后一位截止日期为 21658502507、2165850250、216585025 .. 2. 它用于从外部计划中查找最长前缀匹配,在我们的例子中是:`'Tunisia'、'Mobile (ORANGE) ', '2165' ` 很抱歉一开始没有解释清楚。 -
@Used_By_Already 在我的帖子中,我说过我为整个子查询设置了别名,我的意思是我替换了以 ` (SELECT SPLIT(clear_number) ... AS splitted_number ` 开头的整个块接下来的部分以 `SELECT CONCAT_WS(" - ",country,region) AS route_name ... ` 开头