我需要能够区分两个查询的结果,显示“旧”集中但不在“新”中的行...然后显示“新”中的行“但不是旧的。”
现在,我将结果拉入数组,然后执行array_diff()。但是,我正在遇到一些资源和时间问题,因为这些集合各自接近100万行。
两个结果集中的模式相同(除了setId数和表的自动增量数),所以我假设有一个很好的方法直接在MySQL中进行...但我没有找到如何。
Example Table Schema:
rowId,setId,userId,name
Example Data:
1,1,user1,John
2,1,user2,Sally
3,1,user3,Tom
4,2,user1,John
5,2,user2,Thomas
6,2,user4,Frank
我需要做的是弄清楚setId 1和setId 2之间的添加/删除。
因此,diff的结果应该(例如)显示:
Rows that are in both setId1 and setId2
1,1,user1,John
Rows that are in setId 1 but not in setId2
2,1,user2,Sally
3,1,user3,Tom
Rows that are in setId 2 but not in setId1
5,2,user2,Thomas
6,2,user4,Frank
我认为这就是所有细节。而且我认为我的例子是正确的。任何帮助,将不胜感激。 MySQL或PHP的解决方案对我来说很好。
答案 0 :(得分:0)
您可以使用exists
或not exists
来获取两者中的行或仅有一组的行。
第1组但未设置为2的用户(只是反向翻转表):
select * from set1 s1
where set_id = 1
and not exists (
select count(*) from set1 s2
where s1.user1 = s2.user1
)
两个集合中的用户
select * from set2 s2
where set_id = 2
and exists (
select 1 from set1 s1
where s1.setId = 1
and s2.user1 = s1.user1
)
如果您只想要两个群组中的不同用户,请group by user1
:
select min(rowId), user1 from set1
where set_id in (1,2)
group by user1
having count(distinct set_id) = 2
或群组中的用户,而不是其他用户
select min(rowId), user1 from set1
where set_id in (1,2)
group by user1
having count(case when set_id <> 1 then 1 end) = 0
答案 1 :(得分:0)
我们最终做的是将校验和列添加到所需的表格中。这样,不必选择多列进行比较,可以针对单个列(校验和值)完成差异。
校验和值是序列化数组的简单md5散列,其中包含要扩散的列。所以...在PHP中就是这样:
$checksumString = serialize($arrayOfColumnValues);
$checksumValue = md5($checksumString);
然后将$ checksumValue插入/更新到表中,然后我们可以更容易地在单个列上执行连接/联合等以查找差异。它最终看起来像这样:
SELECT i.id, i.checksumvalue
FROM SAMPLE_TABLE_I i
WHERE i.checksumvalue not in(select checksumvalue from SAMPLE_TABLE_II)
UNION ALL
SELECT ii.id, ii.checksumvalue
FROM SAMPLE_TABLE_II ii
WHERE ii.checksumvalue not in(select checksumvalue from SAMPLE_TABLE_I);
这足以达到我的目的,至少目前为止: - )