Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL-使用一个智能WHERE减少选择次数_Mysql - Fatal编程技术网

MySQL-使用一个智能WHERE减少选择次数

MySQL-使用一个智能WHERE减少选择次数,mysql,Mysql,我有一个包含3列的表,其中保存了一些四位数的id。就像这样: + main_id + id_1 + id_2 + id_3 + |---------|------|------|------| | 1 | 1000 | 1500 | 1900 | | 2 | 1001 | 1501 | 1901 | | 3 | 1002 | 1502 | 1902 | +---------+------+------+------+ 其思想是,这些值不能通过其他组合重复它们

我有一个包含3列的表,其中保存了一些四位数的
id
。就像这样:

+ main_id + id_1 + id_2 + id_3 +
|---------|------|------|------|
|    1    | 1000 | 1500 | 1900 |
|    2    | 1001 | 1501 | 1901 |
|    3    | 1002 | 1502 | 1902 |
+---------+------+------+------+
其思想是,这些值不能通过其他组合重复它们自己。我的意思是,如果表已经有
1001-1501-1901
,那么像
1001-1901-1501
1501-1001-1901
这样的组合就不能再出现在表中,并且应该指向带有
main\u id
的初始组合,并且在任何情况下都应该返回
2

为此,我获得了一个存储函数,我将所有三个
id
传递给它,并在退出时获得
main\u id
,如下所示:

SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id1 AND `id_2` = id2 AND `id_3` = id3) LIMIT 1);

IF (temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id1 AND `id_2` = id3 AND `id_3` = id2) LIMIT 1);
    IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id2 AND `id_2` = id1 AND `id_3` = id3) LIMIT 1);
        IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id2 AND `id_2` = id3 AND `id_3` = id1) LIMIT 1);
            IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id3 AND `id_2` = id1 AND `id_3` = id2) LIMIT 1);
                IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id3 AND `id_2` = id2 AND `id_3` = id1) LIMIT 1);
                END IF;
            END IF;
        END IF;
    END IF;
END IF;

RETURN temp_id;
SELECT `main_id` FROM `tableName`
  WHERE (((`id_1` = id1 AND `id_2` = id2 AND `id_3` = id3)
    OR (`id_1` = id2 AND `id_2` = id1 AND `id_3` - id3)
    ...
    )) LIMIT 1
我考虑在一个
SELECT
with
操作符中使用
WHERE
子句中所有可能的组合,如下所示:

SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id1 AND `id_2` = id2 AND `id_3` = id3) LIMIT 1);

IF (temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id1 AND `id_2` = id3 AND `id_3` = id2) LIMIT 1);
    IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id2 AND `id_2` = id1 AND `id_3` = id3) LIMIT 1);
        IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id2 AND `id_2` = id3 AND `id_3` = id1) LIMIT 1);
            IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id3 AND `id_2` = id1 AND `id_3` = id2) LIMIT 1);
                IF(temp_id IS NULL) THEN SET temp_id = (SELECT `main_id` FROM `tableName` WHERE (`id_1` = id3 AND `id_2` = id2 AND `id_3` = id1) LIMIT 1);
                END IF;
            END IF;
        END IF;
    END IF;
END IF;

RETURN temp_id;
SELECT `main_id` FROM `tableName`
  WHERE (((`id_1` = id1 AND `id_2` = id2 AND `id_3` = id3)
    OR (`id_1` = id2 AND `id_2` = id1 AND `id_3` - id3)
    ...
    )) LIMIT 1
但它将贯穿所有可能的解决方案,在发现时不会停止。如果找到组合,前面的示例至少会停止深入

只有三列,我总共得到6个组合。我计划对4列和5列做同样的事情,总共给我提供大量的select查询

问题是,有没有办法加速这个功能?减少我发送的
SELECT
查询的数量?我使用InnoDB,也许更快的东西会派上用场

更新


我需要为一组三个值提取一个主id。到目前为止,没完没了的
if
语句是最快的解决方案。我正在寻找一种优化方法。

SQL Fiddle目前似乎不稳定,但下面是一个简单的示例,在我的评论中演示了该技术

假设您正在查找与值1002、1502和1902相对应的主_id:

select main_id
from ids main
where exists (select 1 from ids where main.main_id = ids.main_id and id_1 in (select 1502 union select 1002 union select 1902))
and exists (select 1 from ids where main.main_id = ids.main_id and id_2 in (select 1502 union select 1002 union select 1902))
and exists (select 1 from ids where main.main_id = ids.main_id and id_3 in (select 1502 union select 1002 union select 1902))

在您的情况下,您可以将其重构到存储过程中,并使用一个临时表来存储输入值,而不是union。

我建议将ID连接在一起以形成一个唯一的表示形式,然后使用它来删除重复项:

select t.*, m.cnt as NumDups
from (select min(main_id) as main_id, count(*) as cnt
             concat(least(id_1, id_2, id_3),
                    (id_1 + id_2 + id_3) - least(id_1, id_2, id_3) - greatest(id_1, id_2, id_3),
                    greatest(id_1, id_2, id_3)
                   ) as ids
      from tablename t
      group by ids
     ) m join
     tablename t
     on m.main_id = t.main_id;
编辑:

如果要查找一个匹配项,并且变量
@id1
@id2
@id3
包含这些值,则可以执行以下操作:

select t.*
from tablename t
where least(@id1, @id2, @id3) = least(id_1, id_2, id_3) and
      ((@id1 + @id2 + @id3 - least(@id1, @id2, @id3) - greatest(@id1, @id2, @id3)) =
       (id_1 + id_2 + id_3) - least(id_1, id_2, id_3) - greatest(id_1, id_2, id_3)
      ) and
      greatest(@id1, @id2, @id3) = greatest(id_1, id_2, id_3);

使用union规范化原始表,然后可以通过简单的SQL解决这个问题

select main_id,group_concat(id)
from 
    (
    select main_id,id_1 as id from tablename
    union all
    select main_id,id_2 as id from tablename
    union all
    select main_id,id_3 as id from tablename
    ) as ids
where
    id in (1001,1501,1901)
group by
    main_id
having count(*) = 3

@草莓有可能超过3列,没有问题。顺序也不重要。一种方法是从要查找的值构造一个单列表(可以使用union),然后选择所有列所在的IDtable@Strawberry如果顺序不重要,那么解决方案肯定是从最低到最高存储值(与您的示例完全相同)。@草莓我需要为一组三个值提取一个
main\u id
。到目前为止,没完没了的
if
语句是最快的解决方案。我正在寻找一种优化方法。看起来这对任何超过3个人来说都是很麻烦的columns@Strawberry . . . 也许吧,但是这个查询非常明确地涉及3列。嗯,像“我计划对4列和5列做同样的事情”这样的注释和语句不算数?不过,我并不是说我有更好的主意——因为我没有!!抱歉,但这看起来真的像拐杖驱动的开发解决方案。我有一种感觉(测试表明这一点),我的pokecode会演变成SlowBookCode。@Nordenheim。你是说这比你目前的方法慢吗?那么,您是在寻找一个匹配项,还是在寻找整个表的一组简化值?