Есть ли лучшее решение проблемы поиска нескольких известных идентификаторов в таблице:
SELECT * FROM some_table WHERE id='1001' OR id='2002' OR id='3003' OR ...
У меня может быть несколько сотен известных предметов. Идеи?
Есть ли лучшее решение проблемы поиска нескольких известных идентификаторов в таблице:
SELECT * FROM some_table WHERE id='1001' OR id='2002' OR id='3003' OR ...
У меня может быть несколько сотен известных предметов. Идеи?
SELECT * FROM some_table WHERE ID IN ('1001', '1002', '1003')
и если ваши известные идентификаторы поступают из другой таблицы
SELECT * FROM some_table WHERE ID IN (
SELECT KnownID FROM some_other_table WHERE someCondition
)
Первая (наивная) опция:
SELECT * FROM some_table WHERE id IN ('1001', '2002', '3003' ... )
Однако мы должны быть в состоянии сделать лучше. IN
очень плохо, когда у вас много предметов, и вы упомянули сотни этих идентификаторов. Что их создает? Откуда они? Вы можете написать запрос, который возвращает этот список? Если да:
SELECT *
FROM some_table
INNER JOIN ( your query here) filter ON some_table.id=filter.id
OR SQL, как известно, медленны в SQL.
Ваш вопрос не соответствует специфике, но в зависимости от ваших требований и ограничений я бы построил справочную таблицу с вашими идентификаторами и использовал предикат EXISTS:
select t.id from some_table t
where EXISTS (select * from lookup_table l where t.id = l.id)
Для фиксированного набора идентификаторов вы можете:
SELECT * FROM some_table WHERE id IN (1001, 2002, 3003);
Для набора, который изменяется каждый раз, вам может понадобиться создать таблицу для их хранения, а затем запросить:
SELECT * FROM some_table WHERE id IN
(SELECT id FROM selected_ids WHERE key=123);
Другой подход - использовать коллекции - синтаксис для этого будет зависеть от вашей СУБД.
Наконец, всегда существует такой "клочковый" подход:
SELECT * FROM some_table WHERE '|1001|2002|3003|' LIKE '%|' || id || '|%';
В Oracle
я всегда ставил id
в TEMPORARY TABLE
для выполнения массивных операций SELECT
и DML
:
CREATE GLOBAL TEMPORARY TABLE t_temp (id INT)
SELECT *
FROM mytable
WHERE mytable.id IN
(
SELECT id
FROM t_temp
)
Вы можете заполнить временную таблицу в одном клиентском сервере с помощью Oracle
типов коллекций.
У нас есть аналогичная проблема в приложении, написанном для MS SQL Server 7. Хотя мне не нравится используемое решение, мы не знаем ничего лучшего...
"Лучшие" решения существуют в 2008 году, насколько я знаю, но у нас есть клиенты Zero, которые используют это:)
Мы создали функцию, зависящую от таблицы, которая использует строку идентификаторов с разделителями-запятыми и возвращает таблицу идентификаторов. SQL тогда читается достаточно хорошо, и ни один из них не является динамическим, но все еще есть раздражающие двойные накладные расходы:
1. Клиент объединяет идентификаторы в строку.
2. SQL Server анализирует строку для создания таблицы идентификаторов
Существует множество способов превратить "1,2,3,4,5" в таблицу идентификаторов, но хранимая процедура, использующая эту функцию, выглядит как...
CREATE PROCEDURE my_road_to_hell @IDs AS VARCHAR(8000)
AS
BEGIN
SELECT
*
FROM
myTable
INNER JOIN
dbo.fn_split_list(@IDs) AS [IDs]
ON [IDs].id = myTable.id
END
Самый быстрый - добавить идентификаторы в другую таблицу и ПРИСОЕДИНЯЙТЕСЬ
SELECT some_table.*
FROM some_table INNER JOIN some_other_table ON some_table.id = some_other_table.id
где some_other_table будет иметь только одно поле (ids), и все значения будут уникальными