Редактировать: оптимизировано.
Stream
только. Исходные объекты не изменены.
Немного долго, однако.
final Map<String, List<String>> region1 = new LinkedHashMap<>();
region1.put("R1", new ArrayList<>(Arrays.asList("A", "B", "C", "D")));
final Map<String, List<String>> region2 = new LinkedHashMap<>();
region2.put("R2", new ArrayList<>(Arrays.asList("A", "G", "C", "B")));
region2.put("R3", new ArrayList<>(Arrays.asList("A", "G", "C", "B")));
final Stream<Entry<String, List<String>>> entries =
region1.values()
.stream()
.flatMap(values ->
region2.entrySet()
.stream()
.map(e -> {
final List<String> value =
e.getValue()
.stream()
.filter(v -> !values.contains(v))
.collect(toList());
return new SimpleEntry<>(e.getKey(), value);
})
);
final Map<String, List<String>> result = entries.collect(toMap(Entry::getKey, Entry::getValue));
И именно поэтому мне нравятся Stream
с. С выводом типа (Java 10+
) это даже чище.
Нет никакого «внутреннего» порядка в таблице SQL, поэтому вам нужно будет указать некоторое предложение ORDER BY, чтобы придать этой фразе «до» какое-либо значение. Учитывая, что сумма `` первых '' N записей может быть получена с помощью SELECT SUM (деньги) ОТ студента ORDER BY xxx LIMIT N. Используя вспомогательную таблицу INTS, которая имеет целые числа в естественном порядке, вы можете найти максимально подходящий N чем-то вроде:
SELECT MAX(N) FROM INTS
WHERE (SELECT SUM(money) FROM student ORDER BY xxx LIMIT N) < 1000
и, наконец, вставьте его как еще один вложенный SELECT для предложения LIMIT в вашем общем SELECT. Все это пахнет, как будто это было бы довольно неэффективно, хотя! Как часто, когда вложенные SELECT кажутся слишком большими и слишком медленными, альтернатива делает это поэтапно: сначала создайте временную таблицу с «прогрессивными суммами», а затем используйте ее, чтобы найти нужный вам предел.
Упс ... MySQL ... это решение для MS SQL ...
Вот решение с использованием функции ROW_NUMBER ().
SELECT Student.*, SUM(StudentBefore.Money) AS AccumulatedMoney
FROM (
SELECT *, ROW_NUMBER() OVER(ORDER BY Id) AS RowNumber
FROM Students
) AS Student
INNER JOIN
(
SELECT *, ROW_NUMBER() OVER(ORDER BY Id) AS RowNumber
FROM Students
) AS StudentBefore
ON StudentBefore.RowNumber <= Student.RowNumber
GROUP BY Student.RowNumber, Student.Id, Student.Name, Student.Money
HAVING SUM(StudentBefore.Money) < 1000
План выполнения указывает, что сортировка таблицы является самой дорогой операцией. Если в столбцах для сортировки имеется индекс - пример показывает, что вы хотите отсортировать по идентификатору первичного ключа - сканирование индекса станет самой дорогой операцией.