Эффективное хранение совпадающих пар чисел в SQLite - PullRequest
0 голосов
/ 20 марта 2020

Я создаю базу данных SQLite, которая будет служить для хранения информации о парах генов (ортологов). Каждый идентификатор гена (целое число) связан с идентификатором таксона (также целым числом). Каждая строка таблицы (как у меня сейчас) содержит четыре числа: таксон1, ген1, таксон2, ген2, например

taxon1  gene1   taxon2  gene2
7955    571872  7994    103025831
7955    571872  31033   101063396
9031    395159  7955    767804
9031    395159  8128    100690390
9031    395159  9103    100544288

Теперь, если я хочу посмотреть все гены, которые образуют пару между двумя таксонами скажем, 25 и 37, мне нужно выполнить два запроса, так как я не могу гарантировать, что 25 находится в первом столбце:

SELECT taxon1, gene1, taxon2, gene2 FROM orthologs WHERE taxon1=25 AND taxon2=37
SELECT taxon2, gene2, taxon1, gene1 FROM orthologs WHERE taxon2=25 AND taxon1=37

Аналогично, если я хочу, чтобы все гены, которые соответствуют гену 123 из таксон 55 Мне нужно поискать и ген1, и ген2.

Я не знаю много SQL, но это не похоже на эффективное решение; может я что то упускаю? Может быть, есть гораздо лучший способ решить эту проблему? Конечно, я мог бы иметь две таблицы (одну для отображения генов в таксонах, а вторую для пар генов), но мне все равно приходилось бы время от времени искать оба столбца второй.

Моя главная задача размер файла SQLite, он должен быть как можно меньше.

Ответы [ 2 ]

2 голосов
/ 20 марта 2020

Вы можете использовать функции MIN() и MAX():

SELECT taxon1, gene1, taxon2, gene2 
FROM orthologs 
WHERE MIN(taxon1, taxon2) = 25 AND MAX(taxon1, taxon2) = 37

Если значения 25 и 37 являются параметрами, вы можете сделать это:

SELECT taxon1, gene1, taxon2, gene2 
FROM orthologs 
WHERE MIN(taxon1, taxon2) = MIN(:param1, :param2) AND MAX(taxon1, taxon2) = MAX(:param1, :param2)

Существует также опция ROW VALUES с оператором IN:

SELECT taxon1, gene1, taxon2, gene2 
FROM orthologs 
WHERE (taxon1, taxon2) IN((25, 37), (37, 25))

или:

WHERE (25, 37) IN((taxon1, taxon2), (taxon2, taxon1))

Вы также можете использовать это для своего второго требования:

SELECT taxon1, gene1, taxon2, gene2 
FROM orthologs 
WHERE (55, 123) IN((taxon1, gene1), (taxon2, gene2))
1 голос
/ 20 марта 2020

Во многих базах данных вы можете использовать least() и greatest() для этого. Но SQLite не поддерживает их, поэтому мы можем эмулировать их с помощью условных выражений:

where 
    case when taxon1 < taxon2 then taxon1 else taxon2 end = 25
    and case when taxon1 > taxon2 then taxon1 else taxon2 end = 37

Или еще лучше, вы можете использовать min() и max(), как продемонстрировано в ответе forpas (+1) .

Тем не менее, если вы ищете эффективность, вы должны реализовать правило хранения, чтобы, например, самый маленький таксон всегда хранился в taxon1. Это дает вам возможность упростить все это как:

where taxon1 = 25 and taxon2 = 37

Вы можете сделать это с ограничением check:

create table orthologs (
    taxon1 integer,
    ...
    check(taxon1 < taxon2)
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...