Использование IN с наборами кортежей в SQL (SQLite3)
У меня есть следующая таблица в базе данных SQLite3:
CREATE TABLE overlap_results (
neighbors_of_annotation varchar(20),
other_annotation varchar(20),
set1_size INTEGER,
set2_size INTEGER,
jaccard REAL,
p_value REAL,
bh_corrected_p_value REAL,
PRIMARY KEY (neighbors_of_annotation, other_annotation)
);
Я хотел бы выполнить следующий запрос:
SELECT * FROM overlap_results WHERE
(neighbors_of_annotation, other_annotation)
IN (('16070', '8150'), ('16070', '44697'));
То есть у меня есть пара кортежей идентификаторов аннотаций, и я хотел бы получить записи для каждого из этих кортежей. Приглашение sqlite3 выдает мне следующую ошибку:
SQL error: near ",": syntax error
Как правильно выразить это как оператор SQL?
РЕДАКТИРОВАТЬ Я понимаю, что я не объяснил, что я на самом деле после Позвольте мне попробовать еще одну трещину в этом.
Если человек дает мне произвольный список терминов в neighbors_of_annotation
что они заинтересованы, я могу написать оператор SQL, как показано ниже:
SELECT * FROM overlap_results WHERE
neighbors_of_annotation
IN (TERM_1, TERM_2, ..., TERM_N);
Но теперь предположим, что этот человек хочет дать мне пары терминов, если форма (TERM_1,1, TERM_1,2)
, (TERM_2,1, TERM_2,2)
,..., (TERM_N,1, TERM_N,2)
, где TERM_i,1
в neighbors_of_annotation
а также TERM_i,2
в other_annotation
, Предоставляет ли язык SQL одинаково элегантный способ формулировать запрос для интересующих пар (кортежей)?
Кажется, самое простое решение состоит в том, чтобы создать новую таблицу только для этих пар, а затем объединить эту таблицу с таблицей для запроса и выбрать только те строки, в которых совпадают первые и вторые термины. Создание тонн AND /
OR
заявления выглядят страшно и подвержены ошибкам.
2 ответа
Я никогда не видел такой SQL. Если бы он существовал, я бы заподозрил, что это нестандартное расширение. Пытаться:
SELECT * FROM overlap_results
WHERE neighbors_of_annotation = '16070'
AND other_annotation = '8150'
UNION ALL SELECT * FROM overlap_results
WHERE neighbors_of_annotation = '16070'
AND other_annotation = '44697';
Другими словами, создайте динамический запрос из ваших кортежей, но вместо этого, как последовательность объединений или как последовательность AND внутри OR:
SELECT * FROM overlap_results
WHERE (neighbors_of_annotation = '16070' AND other_annotation = '8150')
OR (neighbors_of_annotation = '16070' AND other_annotation = '44697');
Итак, вместо кода (псевдокод, проверенный только в моей голове, так что отладка - ваша ответственность), такого как:
query = "SELECT * FROM overlap_results"
query += " WHERE (neighbors_of_annotation, other_annotation) IN ("
sep = ""
for element in list:
query += sep + "('" + element.noa + "','" + element.oa + "')"
sep = ","
query += ");"
вместо этого у вас будет что-то вроде:
query = "SELECT * FROM overlap_results "
sep = "WHERE "
for element in list:
query += sep + "(neighbors_of_annotation = '" + element.noa + "'"
query += " AND other_annotation = '" + element.oa + "')"
sep = "OR "
query += ";"
Мне не известны какие-либо диалекты SQL, которые поддерживают кортежи внутри предложений IN. Я думаю, что вы застряли с:
SELECT * FROM overlap_results WHERE (neighbors_of_annotation = '16070' and other_annotation = '8150') or (neighbors_of_annotation = '16070' and other_annotation = '44697')
Конечно, этот конкретный запрос может быть упрощен до чего-то вроде:
SELECT * FROM overlap_results WHERE neighbors_of_annotation = '16070' and (other_annotation = '8150' or other_annotation = '44697')
Обычно предикаты SQL-предложения WHERE разрешают фильтрацию только по одному столбцу.