Есть ли более эффективный способ сделать это SQL Select? - PullRequest
3 голосов
/ 19 ноября 2008

У меня есть этот запрос SQL:

SELECT * FROM IMAGES WHERE
IMAGENAME in ('IMG1', 'IMG2', 'IMG3', 'IMG4', 'IMG5', 'IMG6')
ORDER BY CASE IMAGENAME
  WHEN 'IMG1' THEN 1
  WHEN 'IMG2' THEN 2
  WHEN 'IMG3' THEN 3
  WHEN 'IMG4' THEN 4
  WHEN 'IMG5' THEN 5
  WHEN 'IMG6' THEN 6
  ELSE 7
END

Я не могу гарантировать, что список IMAGENAME будет в алфавитном порядке, следовательно, оператор case, но я бы предпочел сортировать в БД, а не в коде, потому что я доверяю их коду сортировки лучше, чем моему:)

SQL-сервер анализирует, что 78% времени выполнения тратится на сортировку - можно ли это уменьшить?

Это должен быть довольно ванильный SQL, поскольку мы нацелены на SQL Server и Oracle.

Любой совет по настройке был бы фантастическим.

Ответы [ 9 ]

6 голосов
/ 19 ноября 2008

Я не уверен, что это доступно в ваших целевых базах данных, но, надеюсь, это может послужить вдохновением для лучшего подхода. В MySQL вы будете делать то, что хотите, с помощью функции FIELD (), например:

SELECT * FROM IMAGES WHERE
  IMAGENAME IN ('IMG1', 'IMG2', 'IMG3', 'IMG4', 'IMG5', 'IMG6')
  ORDER BY FIELD(IMAGENAME, 'IMG1', 'IMG2', 'IMG3', 'IMG4', 'IMG5', 'IMG6');

Функция FIELD () принимает первый параметр, а затем возвращает целое число, основанное на позиции в списке параметров, или ноль, если его нет в списке параметров. Это позволяет вам создать полностью индивидуальный заказ для вашего запроса.

http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_field

Я ожидаю, что нечто подобное может быть доступно в SQL Server или Oracle.

2 голосов
/ 19 ноября 2008
SELECT *
FROM IMAGES
WHERE IMAGENAME in ('IMG1', 'IMG2', 'IMG3', 'IMG4', 'IMG5', 'IMG6')
ORDER BY IMAGENAME ASC

Вам не нужно удалять имя изображения; Вы выбираете только несколько случаев, отмеченных выше, и порядок по может достаточно хорошо упорядочить строку. Кроме того, условие 'else' не имеет смысла, потому что оно никогда не будет использовано, поскольку вы удалили все остальные опции в предложении where.

примечание: это основано на запросе, который вы разместили, если есть больше условий или возможностей, вы также должны предоставить их.

0 голосов
/ 20 ноября 2008

Создать новую таблицу, которая содержит отношение

(IMAGENAME, SEQUENCENUMBER).

Загрузите его с помощью ('IMG1', 1), ('IMG2', 2), ('IMG3', 3), ... Присоединяйтесь к этой таблице в вашем запросе и заказывайте по SEQUENCENUMBER.

Он должен работать намного быстрее.

0 голосов
/ 20 ноября 2008

Если у вас есть возможность добавить индекс, то (на сервере sql), если вы определите кластерный индекс для IMAGENAME, данные будут предварительно отсортированы. Даже если строки не были отсортированы в правильном порядке, они будут по крайней мере сгруппированы по IMAGENAME, поэтому сортировка должна быть более быстрой. Если вы добавляете числовой столбец, поместите в него кластерный индекс. Альтернативой добавлению столбца будет таблица поиска. Но у вас может не быть открытых этих опций

0 голосов
/ 19 ноября 2008

Существует почти эквивалентный способ сделать то, что ChrisThomas123 предложил в SQL Server (но не ORACLE), а именно:

ORDER BY CHARINDEX(IMAGENAME, 'A,B,C,D,E,F,G')

но, похоже, не быстрее.

0 голосов
/ 19 ноября 2008

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

Я подумаю над добавлением числового столбца, чтобы ускорить сортировку.

0 голосов
/ 19 ноября 2008

Если все ваши изображения названы «IMG», то вы должны иметь возможность вставить имя из символа 4, а затем преобразовать его в число. Я не знаю функции SQL Server для этого, но в Oracle это будет:

SELECT * FROM IMAGES WHERE
IMAGENAME in ('IMG1', 'IMG2', 'IMG3', 'IMG4', 'IMG5', 'IMG6')
ORDER BY TO_NUMBER(SUBSTR(IMAGENAME,4));
0 голосов
/ 19 ноября 2008

Вы можете попробовать отсортировать по

CAST(SUBSTRING(IMAGENAME, 4, LEN(IMAGENAME) -3) as INTEGER)

Это, вероятно, не будет работать в Oracle без некоторой настройки, а также может быть не быстрее, чем у вас

Думаю, вам лучше добавить какой-нибудь столбец ранга в таблицу и установить его при записи в него

0 голосов
/ 19 ноября 2008

Не могли бы вы выделить IMG (или не числовую) часть IMAGENAME в новый столбец при записи в базу данных, а затем отсортировать по новому только числовому столбцу?

Например:

SELECT * FROM IMAGES WHERE
IMAGENAME in ('IMG1', 'IMG2', 'IMG3', 'IMG4', 'IMG5', 'IMG6')
ORDER BY IMAGENO
END

где IMAGENO будет содержать 1, 2, 3, 4, 5, 6 для каждой строки в вашем примере, соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...