LINUX.ORG.RU

Поиск отсутствуюших записей

 ,


0

1

Есть таблица, а в ней id, но некоторых заисей нет и их надо найти, пока тупо перебираю:


while True:
	lastid = lastid-1
	cur.execute("select * from files where id = ?", [lastid])
	if not cur.fetchone():
		return lastid

Так работает, но некрасиво и долго, а как одим запросом все выбрать?

PS id не AUTOINCREMENT и идет не с 1



Последнее исправление: calebfedorov (всего исправлений: 1)

зависит от количества данных в таблице. если не так уж и много, то можно сразу загрузить всё и перебирать уже в памяти, а по одному тягать - это не так продуктивно. но если объёмы таблицы большие, то легче тягать по одному или блоками:

a = session.query(Files).all()

for i in a:
    pass

session.query(Files).filter_by(ide=ide).one()

a = session.query(Files).offset(???).limit(???).all()

for i in a:
    pass

AGUtilities ★★★
()
Последнее исправление: AGUtilities (всего исправлений: 1)

Записей в таблице около 50k Отсутствующих не более сотни, думаю оптимальный вариант выбрать их одним запросом и поместить в массив...

calebfedorov
() автор топика

Принцип генерации id известен? Тогда сделай два списка.

  • y = полный список всех допустимых id
  • x = список id из sqlite

Дальше можно в коде python найти элементы списка, которые есть в 'y', но отсутсвуют в 'x'.

$ python
>>> x = [5,6,9]
>>> x
[5, 6, 9]
>>> y = range(2,10)
>>> y
[2, 3, 4, 5, 6, 7, 8, 9]
>>> z = set(y) - set(x)
>>> z
set([8, 2, 3, 4, 7])
>>> z = list(z)
>>> z
[8, 2, 3, 4, 7]
>>> z.sort()
>>> z
[2, 3, 4, 7, 8]

justAmoment ★★★★★
()
Ответ на: комментарий от justAmoment

То же самое, только покороче.

$ python
>>> x = [5,6,9]
>>> y = range(2,10)
>>> z = sorted(set(y) - set(x))
>>> print "x =",x,"\n","y =",y,"\n","z =",z
x = [5, 6, 9] 
y = [2, 3, 4, 5, 6, 7, 8, 9] 
z = [2, 3, 4, 7, 8]

justAmoment ★★★★★
()

Во-первых, чтобы экономить ОЗУ, в массив выгружай не все поля, а только id:

cur.execute("select id from files")
Если файл небольшой, то уже этого хватит.
Во-вторых, выборку запрашивай сразу сортированную, так удобнее искать «провалы»:
cur.execute("select id from files order by id")
(хотя, если id ключевой индекс, то не обязательно)
В-третьих, если файл большой, можешь ограничить число записей:
lim=1000
cur.execute("select id from files limit ? order by id", [lim])
В-четвертых, следующую порцию выбирай по граничному условию:
lim=1000
firstid=max_id_from_previous_array
cur.execute("select id from files where id > ? limit ? order by id", [firstid,lim])
max_id_from_previous_array - для первой итерации 0, для следущей - максимум у предыдущей.

Другой вариант, без limit - просто увеличивать диапазоны:

firstid=max_id_from_previous_array
lastid=max_id_from_previous_array+1000
cur.execute("SELECT id FROM files WHERE id > ? AND id <= ? ORDER BY id ASC", [firstid,lastid])

Импровизируй :)

Novator ★★★★★
()
Последнее исправление: Novator (всего исправлений: 1)

к примеру

CREATE TABLE 'dat' (
  'value' INTEGER;
);

SELECT
  A.value AS val,
  A.value - max(B.value) AS delta
FROM
  dat as A,
  dat as B
WHERE B.value<A.value
GROUP BY A.value
HAVING delta>1; 
вытащит все 'не инкрементные' value

MKuznetsov ★★★★★
()

По идее надо сjoin'ить табличку саму с собой, но по условия (t1.id = t2.id + 1). А потом сделать выборку без t1.id. Типа так:

select * from files where id not in (
select t1.id from files t1 inner join files t2 on (t1.id = t2.id + 1))

Как-то так

ziemin ★★
()
Ответ на: комментарий от ziemin

И, кстати:

но некоторых заисей нет и их надо найти

поправь формулировку, глаз режет.

ziemin ★★
()
Ответ на: комментарий от MKuznetsov

вытащит все 'не инкрементные' value

а можешь сказать как это на уровне движка работает? Т.е. какие строки в каком порядке он будет вынимать из базы и как сравнивать.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

вообще вопрос ТС настолько типовой, что бывает на лоре раз в месяц-полтора. Детали построения и оптимизации подобных запросов см. в гугле по «нарастающая сумма(итог)». Кстати разбирается во всех книжках по SQL потому как востребован в бухгалериях и финансах.

Приведённый мной скрипт честно скопипастен из своей записной книжки :)

MKuznetsov ★★★★★
()

Я просто смотрел, профилировал, 99% занимает sql.execute.. в sql я не очень шарю, вот пока так...

PS это «очередной» парсер залил ру, написан не по правилам, для себя, но кому надо вышлю...

calebfedorov
() автор топика

Если есть список всех ID где-то, то залить его в табличку допустим «myID». А потом просто: SELECT * FROM files where id not in (select id from myID)

Megamozg
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.