Сумма до определенного момента - MySql

Редактировать: оптимизировано.
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+) это даже чище.

7
задан henry 8 May 2009 в 13:19
поделиться

2 ответа

Нет никакого «внутреннего» порядка в таблице 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 кажутся слишком большими и слишком медленными, альтернатива делает это поэтапно: сначала создайте временную таблицу с «прогрессивными суммами», а затем используйте ее, чтобы найти нужный вам предел.

2
ответ дан 7 December 2019 в 07:50
поделиться

Упс ... 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  

План выполнения указывает, что сортировка таблицы является самой дорогой операцией. Если в столбцах для сортировки имеется индекс - пример показывает, что вы хотите отсортировать по идентификатору первичного ключа - сканирование индекса станет самой дорогой операцией.

1
ответ дан 7 December 2019 в 07:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: