почему то, что я сделал, не работает?
Рассмотрим условие ГДЕ:
rowid not in (SELECT distinct(timestamp) from tablename)
Простой ответ заключается в том, что вы не сравниваете данные в одних и тех же столбцах, и при этом они не являются столбцами с данными одного типа. rowid
- это автоматически увеличиваемый столбец целых чисел, и я предполагаю, что столбец timestamp
является числовым или строковым столбцом, содержащим значения времени, или, возможно, сгенерированные пользователем последовательные числовые значения. Поскольку rowid
вероятно никогда не соответствует значению timestamp
, операция NOT IN
будет всегда возвращать true . Таким образом, каждая строка таблицы будет удалена.
SQL довольно явный, поэтому нет никаких скрытых / таинственных сравнений столбцов. Он не будет автоматически сравнивать значения строк из одного запроса с другим. Обратите внимание, что различные альтернативные операторы делают что-то, чтобы различать строки с дублирующимися значениями ключа (timestamp
в вашем случае), либо путем прямого сравнения основного запроса и подзапроса, либо с помощью оконных функций для уникальной маркировки строк с дубликатом значения и т. д.
Просто для удовольствия, вот еще одна альтернатива, которая использует NOT IN
как ваш оригинальный код.
DELETE FROM tablename
WHERE rowid NOT IN (
SELECT max(t.rowid) FROM tablename t
GROUP BY t.timestamp )
Сначала обратите внимание, что это сравнение rowid
с max(t.rowid)
, значениями, которые получены из того же столбца.
Поскольку подзапрос группируется по t.timestamp
, агрегатная функция max()
будет возвращать наибольшее / последнее t.rowid
отдельно для каждого набора строк с одинаковым значением t.timestamp
. Результирующий список исключит t.rowid
значений, которые меньше максимального. Таким образом, операция NOT IN
не найдет эти меньшие значения и вернет true
, поэтому они будут удалены.
Он также использует базовый SQL (без оконных функций ... ключевое слово OVER). Вероятно, будет более эффективным , чем альтернатива, которая ссылается на внешний запрос из подзапроса, потому что этот оператор может выполнить подзапрос только один раз, а затем использовать эффективный индекс для сопоставления отдельных записей ... он не необходимо повторно выполнить запрос для каждой строки. В этом отношении она также должна быть более эффективной, чем оконная функция, потому что оконное разбиение по существу «группируется» в разделенных столбцах, но затем должно выполнять оконную функцию для каждой строки, что является дополнительным шагом, отсутствующим в базовом агрегированном запросе. Эффективность не всегда важна, но важно учитывать.
Кстати, отличное ключевое слово не является функцией и не требует / принимает круглые скобки. Это директива, которая применяется ко всему оператору выбора. Подзапрос интерпретируется как
SELECT DISTINCT (timestamp) FROM tablename
где DISTINCT интерпретируется изолированно, а скобки интерпретируются как отдельное выражение.
Обновление
Эти два запроса вернут одинаковые данные:
SELECT DISTINCT timestamp FROM tablename;
SELECT timestamp FROM tablename GROUP BY timestamp;
Оба результата удаляют повторяющиеся строки из выходных данных, показывая только уникальные / отличные значения, но ни один из них не имеет «дескриптора» (другой столбец данных), который указывает, какие строки следует сохранить и какие строки удалить. Другими словами, эти запросы возвращают разные значения, но результаты теряют все связи с исходными строками и поэтому не имеют смысла указывать, какие исходные строки следует удалить (или сохранить). Чтобы лучше понять, вам следует запускать подзапросы отдельно, чтобы проверить, что они возвращают, чтобы вы могли понять и проверить, с какими данными вы работаете.
Чтобы сделать эти запросы полезными, нам нужно сделать что-то, чтобы различать строки с дублирующимися значениями ключа . Строки нуждаются в «дескрипторе» - другом значении ключа, которое нужно выбрать для удаления или сохранения этих строк. Попробуйте это ...
SELECT DISTINCT rowid, timestamp FROM tablename;
Но это не сработает, потому что оно применяет ключевое слово DISTINCT ко ВСЕМ возвращаемым столбцам, но так как rowid уже уникален, он обязательно будет выводить каждую строку отдельно, поэтому в запросе нет смысла.
SELECT max(rowid), timestamp FROM tablename GROUP BY timestamp;
Этот запрос сохраняет уникальную группировку, но предоставляет только один rowid на отметку времени в качестве «дескриптора» для включения / исключения для удаления.