我有一个包含3列的表格,其中包含一些四位数的ids
。像那样:
+ 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_id
并且在任何情况下都应该返回2
。
为此,我得到了一个存储函数,我将所有三个ids
传递给它并在退出时获取main_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;
我考虑过将WHERE
个SELECT
子句中的所有可能组合与OR
运算符一起使用,如下所示:
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
个查询量?我使用InnoDB,也许更快的东西会派上用场?
更新
我需要为一组三个值提取一个主要ID。到目前为止,无休止的if
语句是最快的解决方案。我正在寻找优化。
答案 0 :(得分:1)
我建议将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);
答案 1 :(得分:0)
SQL Fiddle现在似乎不稳定,但这是一个在我的评论中演示该技术的简单示例。
假设您正在寻找与值1002,1502和1902相对应的main_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))
在您的情况下,您可以将其重构为存储过程并使用临时表来存储输入值而不是联合。
答案 2 :(得分:0)
使用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