MySQL:如何在列

时间:2018-01-05 17:08:11

标签: mysql

我有很长的行列表,其中包含随机值:

| id | value |
|----|-------|
|  1 | abcd  |
|  2 | qwer  |
|  3 | jklm  |
|  4 | yxcv  |
|  5 | tzui  |

然后我有几个值的数组:

array('qwer', 'jklm');

我需要知道,如果来自数组的这个值序列已经按照给定的顺序存在于表中。在这种情况下,存在值序列。

我试图从表和数组中连接所有值并匹配两个字符串,这几个行很好用,但实际上表中有数十万行。我相信应该有更好的解决方案。

2 个答案:

答案 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;

SQL Fiddle here