我有一个不同客户(customer_id)的值(数字)表:
CREATE TABLE dev.customer_resources (
id int(11) NOT NULL AUTO_INCREMENT,
customer_id int(11) DEFAULT NULL,
value int(11) DEFAULT NULL,
PRIMARY KEY (id)
)
我想获取特定客户的数字范围。 因此,如果表数据为:
======================
|id|customer_id|value|
======================
| 1| 21| 1|
----------------------
| 2| 21| 2|
----------------------
| 3| 21| 3|
----------------------
| 4| 21| 20|
----------------------
| 5| 21| 21|
----------------------
| 6| 21| 22|
----------------------
| 7| 22| 5|
----------------------
对于customer_id = 21,我会得到类似这样的结果:
==========
start |end
==========
| 1| 3|
----------
| 20|22|
----------
以及针对customer_id = 22的类似内容:
==========
start |end
==========
| 5| 5|
----------
在寻找解决方案之后,我发现了以下代码:
select l.value as start,
(
select min(a.value) as value
from customer_resources as a
left outer join customer_resources as b on a.value = b.value - 1
where b.value is null
and a.value >= l.value
) as end
from customer_resources as l
left outer join customer_resources as r on r.value = l.value - 1
where r.value is NULL;
几乎可以满足我的需要,但不包括将结果限制为特定的customer_id。 我尝试将customer_id添加到查询中,但是我不确定在哪里添加它,因为它所做的只是中断功能。
答案 0 :(得分:2)
LukStorms解决方案似乎是正确的事情-似乎比严格必要的要复杂得多...
这是主题的变种...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,customer_id int NOT NULL
,value int NOT NULL
);
INSERT INTO my_table VALUES
(1, 21, 1),
(2, 21, 2),
(3, 21, 3),
(4, 21, 20),
(5, 21, 21),
(6, 21, 22),
(7, 22, 5);
SELECT customer_id
, MIN(value) start
, MAX(value) end
FROM
( SELECT *
, CASE WHEN value = @prev+1 THEN @i:=@i ELSE @i:=@i+1 END grp
, @prev:=value prev
FROM my_table
, (SELECT @prev:= null,@i:=0) vars
ORDER
BY customer_id
, id
) x
GROUP
BY customer_id,grp;
+-------------+-------+------+
| customer_id | start | end |
+-------------+-------+------+
| 21 | 1 | 3 |
| 21 | 20 | 22 |
| 22 | 5 | 5 |
+-------------+-------+------+
答案 1 :(得分:1)
这似乎是一个缺口和孤岛的问题。
这里有一些使用变量的老式MySql特定解决方案。
通过比较先前的值和customer_id来找到孤岛的起点。
SELECT
customer_id,
value_start as `start`,
max(val) as `end`
FROM
(
SELECT
CASE
WHEN `value` = @prev_val + 1 AND customer_id = @prev_grp
THEN @start_val:= @start_val
ELSE @start_val:=`value`
END AS value_start,
@prev_grp:=customer_id as customer_id,
@prev_val:=`value` as val
FROM customer_resources
CROSS JOIN (SELECT @prev_val:=NULL, @start_val:=NULL, @prev_grp:=NULL) AS v
ORDER BY customer_id, `value`
) AS q
GROUP BY customer_id, value_start;