SQL: выберите «до»

Ищу способ выбора, пока не будет достигнута сумма.

В моей таблице «документы» есть поля «tag_id» и «size».

Я хочу выбрать все документы с помощью tag_id = 26, но знаю, что могу обрабатывать только 600 единиц размера. Итак, нет смысла выбирать 100 документов и отбрасывать 90 из них, когда я мог знать, что первые 10 уже составили> 600 единиц.

Итак, цель такова: не возвращать тонны данных для анализа, когда я собираюсь отбросить большую часть из них.

... но я бы также очень хотел избежать введения в это приложение работы с курсорами.

Я использую mysql.

Есть ли в MySQL аналитические функции?

Mark Brady 13.11.2008 19:07

Поскольку будет много комбинаций документов, добавляемых к> 600, как узнать, какие документы вы хотите использовать? Или все равно?

Kev 13.11.2008 19:08

Предпочтение отдается недавно добавленным документам (есть поле date_created, в котором мы закажем описание)

jhalb 13.11.2008 19:17

Это похоже на работу вашей бизнес-логики / компонента / кода, которая взаимодействует с базой данных, а не на задачу самого запроса.

matt b 13.11.2008 19:17

Мэтт ... с аналитикой это можно сделать в запросе. Если это можно сделать в базе данных, это будет быстрее.

Mark Brady 13.11.2008 19:24

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

Joel Coehoorn 13.11.2008 19:27
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
6
6
5 383
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вам нужен способ упорядочить, какие записи имеют приоритет над другими при добавлении к вашим максимальным единицам. В противном случае, как узнать, какой набор записей, насчитывающий в общей сложности 600, вы храните?

SELECT d.id, d.size, d.date_created
FROM documents d
INNER JOIN documents d2 ON d2.tag_id=d.tag_id AND d2.date_created >= d.date_created
WHERE d.tag_id=26
GROUP BY d.id, d.size, d.date_created
HAVING sum(d2.size) <= 600
ORDER BY d.date_created DESC

Это всего лишь базовый запрос для начала, и еще предстоит решить ряд проблем:

  • Он останавливается на <= 600, поэтому в большинстве случаев вы не сможете точно заполнить свой лимит размера. Это означает, что вы можете захотеть настроить его, чтобы разрешить еще одну запись. Например, если первая запись> 600, запрос ничего не вернет, и это может быть проблемой.
  • Он не будет ничего делать, чтобы позже проверить дополнительные записи меньшего размера, которые все еще могут уместиться под крышкой.
  • Записи с одинаковыми значениями date_created могут быть как бы «подсчитаны дважды» здесь и там.

редактировать
Обновлено, поскольку он добавил информацию, которую он сортирует по дате.

Я начал публиковать что-то очень похожее, правда, используя вспомогательное представление. Ваш лучше.

Joe Pineda 13.11.2008 19:20

Это тоже умнее, чем мой ответ. :)

Kev 13.11.2008 19:22

Это намного менее эффективно, но позволяет избежать курсора (при условии, что в вашей таблице документов также есть столбец с серийным идентификатором):

select a.id, (select sum(b.size) from documents b where b.id <= a.id and b.tag_id = 26)
from documents a
where a.tag_id = 26
order by a.id

Кроме того, это было сделано в pgsql, поэтому я не уверен, будет ли этот точный синтаксис работать в mysql.

Затем вы можете обернуть это в другой запрос, который ищет те, у которых сумма> 600 (вам нужно будет назвать столбец суммы) и взять первый идентификатор. Затем обработайте все идентификаторы ниже, включая этот.

Эээ, если нет идентификатора, тогда используйте созданную метку времени.

Kev 13.11.2008 19:22

Вам нужно сначала сохранить документы в табличной переменной, отсортировать их в том порядке, в котором вы хотите их получить, а затем обновить каждую строку накопительным значением, чтобы вы могли выбрать его.

 declare @documents_temp table (
    tag_id int,
    size int,
    cumulative_size int null)

insert into @documents_temp
select tag_id, size, size from documents order by tag_id

update @documents_temp d set d.cumulative_size = d.size + 
    (select top 1 cumulative_size from @documents_temp 
     where tag_id < d.tag_id order by tag_id desc)

select tag_id, size from @documents_temp where cumulative_size <= 600

Не знаю, стоит ли оно того.

Другие вопросы по теме