我有很长的行列表,其中包含随机值:
| id | value |
|----|-------|
| 1 | abcd |
| 2 | qwer |
| 3 | jklm |
| 4 | yxcv |
| 5 | tzui |
然后我有几个值的数组:
array('qwer', 'jklm');
我需要知道,如果来自数组的这个值序列已经按照给定的顺序存在于表中。在这种情况下,存在值序列。
我试图从表和数组中连接所有值并匹配两个字符串,这几个行很好用,但实际上表中有数十万行。我相信应该有更好的解决方案。
答案 0 :(得分:2)
如果您的列表很短,您可以自行加入并拼出每个联接表引用的条件:
select t1.id from MyTable as t1 join MyTable as t2
where t1.value='qwer' and t2.value='jklm' and t1.id=t2.id-1;
如果没有这样的序列,则返回空集。当然,它假设id号是连续的(它们在你的例子中,但一般来说这是一个冒险的假设)。
如果你的列表真的很长,这不会很好。 MySQL在单个查询中支持63个表引用的硬限制。
这是另一个解决方案,适用于任何大小的列表,但前提是您的id
值已知是连续的:
select t1.id from MyTable as t1 join MyTable as t2
on t2.id between t1.id and t1.id+1
where t1.value = 'qwer' and t2.value in ('qwer','jklm')
group by t1.id
having group_concat(t2.value order by t2.id) = 'qwer,jklm';
t1行是潜在匹配行序列的开头,因此它必须与列表中的第一个值匹配。
然后加入t2行,这些行是可能匹配的行的完整集合。
根据您要搜索的N个值列表的大小,t2行的集合也限制为不超过N行的集合。但SQL无法根据行数创建组,我们只能根据行中的某些值进行限制。因此,如果您的id值可以假设是连续的,那么这就是为什么会起作用的原因。
答案 1 :(得分:1)
这样你可以为整套做到这一点:
select value1, value2
from
(
select *
from (
SELECT [IMEPAC] value1 , ROW_NUMBER() over(order by [MATBR]) rn1
FROM [PACM]
) a1 join
(
SELECT [IMEPAC] value2 , ROW_NUMBER() over(order by [MATBR]) rn2
FROM [PACM]
) a2 on a1.rn1 = a2.rn2 + 1
) a
group by value1, value2
having count(*) > 1
它是为MS SQL编写的,但您也可以轻松地重写它以适应mysql。
我用>对照表运行IMEPAC上的400000行不属于任何索引,它运行(第一次且仅运行一次),持续6秒。
这是Mysql版本:
select value1, value2, count(*) count
from
(
select *
from (
SELECT @row_number1:= @row_number1 + 1 AS rn1, content as value1
FROM docs,(SELECT @row_number1:=0) AS t
order by id
) a1 join
(
SELECT @row_number2:= @row_number2 + 1 AS rn2, content value2
FROM docs,(SELECT @row_number2:=0) AS t
order by id
) a2 on a1.rn1 = a2.rn2 + 1
) a
group by value1, value2
having count(*) > 1;