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

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

6 голосов
/ 13 ноября 2008

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

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

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

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

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

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

Ответы [ 3 ]

7 голосов
/ 13 ноября 2008

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

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

0 голосов
/ 13 ноября 2008

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

 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

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

0 голосов
/ 13 ноября 2008

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

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 (вам нужно будет назвать столбец суммы) и взять первый идентификатор. Затем обработайте все идентификаторы ниже, включая этот.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...