+----------+---------+---------+-----------+-----------+--------------+
| entry_id | item_id | stat_id | stat_type | int_value | string_value |
+----------+---------+---------+-----------+-----------+--------------+
| 1 | 4255 | 10 | int | 54 | NULL |
| 2 | 4255 | 16 | int | 443 | NULL |
| 3 | 4255 | 56 | int | 13 | NULL |
| 4 | 6544 | 10 | int | 54 | NULL |
| 5 | 6544 | 56 | int | 13 | NULL |
| 6 | 6544 | 16 | int | 443 | NULL |
| 7 | 8570 | 56 | int | 13 | NULL |
| 8 | 8570 | 10 | int | 76 | NULL |
| 9 | 8570 | 72 | int | 1 | NULL |
+----------+---------+---------+-----------+-----------+--------------+
以上是我所拥有的表格的示例。 任务是为表提供目标" item_id"价值,回到" item_id"与目标具有相同行的。
在上面的示例中,提供" item_id" 4255将返回6544,在那两个" item_id"值可以在三行中找到,每行在其他方面相互匹配(" entry_id&#34除外)。
从本质上讲,我需要找出是否还有另一个" item_id"在数据库中,它在所有方面都与目标相同。如果它具有相同的行,但也可以在其他行中找到,则不会将其归类为匹配。
是否有可能将此类事物作为SQL查询的一部分? 我目前正在使用C#代码执行此操作,其中我遍历包含目标的每一行" item_id"一个接一个,寻找比赛。这似乎非常低效。
答案 0 :(得分:0)
我认为MySQL中最简单的方法是使用group_concat()
。这有点像黑客,但它应该运作良好 - 假设你可以对NULL
有点灵活:
select t.item_id
from (select item_id,
group_concat(stat_id, '|', stat_type, '|', int_value, '|', coalesce(string_value, '<NULL>' order by stat_id) as fields
from t
group by item_id
) t join
(select item_id,
group_concat(stat_id, '|', stat_type, '|', int_value, '|', coalesce(string_value, '<NULL>' order by stat_id) as fields
from t
where item_id = 4255
) tspecial
on tspecial.fields = t.fields;
注意事项:
NULL
进行一些特殊处理。group_concat()
使用的内部字符串的长度为1,024个字符。如果需要,可以覆盖它。'|'
)。关系解决方案有点复杂。
select i.item_id
from (select distinct item_id from t) i cross join
(select stat_id, stat_type, int_value, string_value
from t where item_id = 4255
) s left join
t
on t.stat_id = s.stat_id and
t.stat_type = s.stat_type and
t.int_value is not distinct from s.int_value and
t.string_value is not distinct from s.string_value
group by i.item_id
having count(*) = count(t.stat_id);
这是如何工作的?它会为所有项目生成所需字段的所有统计信息。然后它执行left join
以匹配其他字段中的值。然后聚合检查匹配统计数量是否与预期数量匹配。
一个优点是此版本对NULL
值或分隔符不具有奇怪的限制。
答案 1 :(得分:0)
假设您没有重复项(组合(item_id, stat_id, stat_type, int_value, string_value)
是唯一的)且只有string_value
可以为NULL,那么您可以加入完全匹配并比较行数(数学的数量必须相等)到两个项目的行数。)
select t2.item_id
from t t1
join t t2 using(stat_id, stat_type, int_value)
where t1.item_id = 4255
and t2.item_id <> t1.item_id
and t2.string_value <=> t1.string_value
group by t1.item_id, t2.item_id
having count(*) = (select count(*) from t where t.item_id = 4255)
and count(*) = (select count(*) from t where t.item_id = t2.item_id)