【pg】多个字段查重过滤

我们通常单主键查询判断,如果来了一个多个字段为主键,判断查重

代码处理

public class Main {
    public static void main(String[] args) {
           //新增,调整为数据查询
			List<StrongBuopSheetInfo> retMap = sqlService.list(dateTime);
			if (CollectionUtils.isNotEmpty(retMap)) {
				retMap = retMap.stream().collect(Collectors.collectingAndThen(
						Collectors.toCollection(() -> new TreeSet<>(
								Comparator.comparing(p -> appendStrings(new String[]{ObjectUtil.toString(p.getDayId()), ";", p.getPrvnceId(), ";", p.getLatnId(), ";", p.getServiceId(), ";", p.getCallNbr()})
								))), ArrayList::new));
			}
}
	/**
	 * 将字符串数组拼接在一起并返回
	 * StringUtil.appendStrings(new String[]{"第", String.valueOf(flag), "条,====> ", sql});
	 * @param strArr
	 * @return
	 */
	public static String appendStrings(String[] strArr) {
		StringBuilder str2 = new StringBuilder();
		if (strArr != null && strArr.length > 0) {
			for (String s : strArr
			) {
				str2.append(s);
			}
		}
		return str2.toString();

	}
}

上面一个问题就是原本7条数据,4条重复,查重后,剩余3条,数据缺少了
如果重复4条,保留其中一条呢?java stream 多个字段重复取其中一条

在Java中,你可以使用Stream API来处理集合数据,并且你可以利用一些特性来找到并处理重复的元素。如果你有一个对象列表,并且你想基于多个字段来找到重复项,并只保留其中一条记录,你可以使用Collectors.toMap来帮助你。

下面是一个示例,假设你有一个Person类,它有两个字段:name和age,你想基于这两个字段来找到重复的人,并只保留一个。

import java.util.*;
import java.util.stream.Collectors;
 
public class Main {
    public static void main(String[] args) {
        List<Person> people = Arrays.asList(
                new Person("Alice", 25),
                new Person("Bob", 30),
                new Person("Alice", 25), // 重复项
                new Person("Charlie", 35),
                new Person("David", 25) // 与Alice年龄相同,但名字不同,所以不是重复项
        );
 
        Map<List<Object>, Person> uniquePersons = people.stream()
                .collect(Collectors.toMap(
                        p -> Arrays.asList(p.getName(), p.getAge()), // 使用名字和年龄作为键
                        Function.identity(), // 值就是Person对象本身
                        (existing, replacement) -> existing // 如果键冲突(即找到重复项),保留现有的Person对象
                ));
 
        // 将结果转换回列表
        List<Person> result = new ArrayList<>(uniquePersons.values());
 
        // 输出结果以验证重复项已被移除
        result.forEach(person -> System.out.println(person.getName() + " " + person.getAge()));
    }
}
 
class Person {
    private String name;
    private int age;
 
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public int getAge() {
        return age;
    }
}

在这个示例中,我们使用Collectors.toMap来创建一个Map,其中键是一个包含名字和年龄的列表,值是Person对象。如果找到具有相同名字和年龄的重复项,我们保留Map中现有的Person对象(这是由合并函数(existing, replacement) -> existing指定的)。最后,我们将Map的值转换回一个列表。

库表查询

如果您正在使用PostgreSQL(通常简称为PG)并希望根据多个字段进行查重和过滤,您可以使用DISTINCT ON或GROUP BY结合HAVING子句来实现。

以下是两种方法的示例:

使用 DISTINCT ON:

假设您有一个名为 my_table 的表,并且您希望基于 field1 和 field2 进行查重,只保留每组中的第一条记录。

SELECT DISTINCT ON (field1, field2) *
FROM my_table
ORDER BY field1, field2, [some_other_field_to_determine_priority];

在这里,[some_other_field_to_determine_priority] 是用来确定在每组中哪条记录应该被保留的字段。通常,这会是一个时间戳或ID字段。

  1. 使用 GROUP BY 和 HAVING:

如果您想基于 field1 和 field2 进行查重,并过滤掉那些重复的记录,只留下每组中的一个代表,您可以这样做:

SELECT field1, field2, MIN(id) as representative_id
FROM my_table
GROUP BY field1, field2
HAVING COUNT(*) > 1;

这将返回所有 field1 和 field2 的组合,这些组合在表中出现的次数超过一次,并且对于每个这样的组合,它将返回具有最小 id 的记录。

根据您的具体需求,您可以选择最适合您的方法。

参考

翻阅痕迹,方便追踪

java stream distinct() 按一个或多个指定对象字段进行去重

你可能感兴趣的:(通用表单,postgresql)