Использование IN с наборами кортежей в SQL (SQLite3) - PullRequest
5 голосов
/ 08 апреля 2010

У меня есть следующая таблица в базе данных 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 ]

4 голосов
/ 08 апреля 2010

Я никогда не видел такой 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 += ";"
2 голосов
/ 08 апреля 2010

Мне не известны какие-либо диалекты 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 разрешают фильтрацию только по одному столбцу.

...