Как правильно назначить порядковые номера упорядоченным строкам в таблице в Sybase?
У меня есть таблица T (структура ниже), которая изначально содержит все NULL-значения в целом числе order
колонка:
col1 varchar (30), col2 varchar (30), заказ int NULL
У меня также есть способ заказать столбцы "colN", например
SELECT * FROM T ORDER BY some_expression_involving_col1_and_col2
Каков наилучший способ присвоения - IN SQL - числовых значений порядка 1-N для таблицы порядка, чтобы значения порядка совпадали с порядком строк, возвращаемых вышеупомянутым ORDER BY?
Другими словами, я хотел бы один запрос (синтаксис Sybase SQL, поэтому нет Oracle rowcount), который назначает order
значения, так что SELECT * FROM T ORDER BY order
возвращает 100% порядок строк, как в запросе выше.
Запрос не обязательно должен обновлять таблицу T на месте, я согласен с созданием копии таблицы T2, если это упростит запрос.
ПРИМЕЧАНИЕ 1. Решением должен быть реальный запрос или набор запросов, не включающий цикл или курсор.
ПРИМЕЧАНИЕ 2. Предположим, что данные могут быть однозначно упорядочены в соответствии с указанным выше порядком - не нужно беспокоиться о ситуации, когда 2 строкам можно назначить один и тот же порядок случайным образом.
ПРИМЕЧАНИЕ 3. Я бы предпочел общее решение, но если вы хотите конкретный пример выражения порядка, скажем:
ВЫБРАТЬ * ОТ Т ЗАКАЗАТЬ ПО СЛУЧАЮ КОГДА col1="" THEN "AAAAAA" ELSE col1 END, ISNULL(col2, "ZZZ")
3 ответа
Я использовал в качестве примера таблицу roysched в pubs2. Я добавил колонку id
(int NULL) и использовал в качестве логики упорядочения следующее:
substring(title_id,3,4) + right(replicate('0',5) + convert(varchar,lorange),5)
Затем я создал (и обновил) представление. Чтобы избежать дублирования, я использовал строки
Declare @strSql varchar(1000), @strOrder varchar(256)
set @strOrder = "substring(title_id,3,4) + right(replicate('0',5) + convert(varchar,lorange),5)"
set @strSql = "create view my_roysched (id,my_order)
as
select id, (select count(*) from (select " + @strOrder + " as my_order from roysched) BETA
where BETA.my_order <= ALPHA.my_order) as my_id
from (select id," + @strOrder + " as my_order from roysched ) as ALPHA
update my_roysched
set id = my_order
drop view my_roysched"
exec (@strSql)
Теперь, если вы дадите
select * from roysched
order by substring(title_id,3,4) + right(replicate('0',5) + convert(varchar,lorange),5)
вы увидите, что id совпадает с порядком строк, возвращаемых вышеуказанным порядком
DVK
Люди ответили на ваш конкретный вопрос, и вы выбрали ответ.
Но у всего вопроса есть более глубокая проблема.
Из того, что я могу понять,
Order
столбец в таблице; который определяет Порядок, в котором должны быть представлены строки (или аналогичные). Это верно?Если это так, то таблица в значительной степени денормализована: вы нарушили 3NF (правило функциональной зависимости нарушено); у вас есть производное значение в столбце (дублированная информация); введены аномалии обновления (когда вы обновляете данные в столбце, теперь вам нужно обновить дублированные [зависимые] данные в другом столбце).
Самым важным из них, конечно же, являются аномалии обновления. Вы больше не можете вставлять строку в (теперь нереляционную, ненормализованную) таблицу. Для каждой вставки вы должны пересчитать и обновить
Order
столбец, по крайней мере, для одной и не более, для каждой второй строки в таблице.Ничего из этого не нужно.
Я мог бы ответить на ваш вопрос только в рамках вашего вопроса, чтобы заполнить
Order
столбец (вызывается сегментом кода, который постоянно поддерживает его). Требуемый код состоит из 5 строк. Чистый стандартный SQL на базовой таблице. Нет просмотров. Нет временных таблиц. Никаких петель или курсоров. Работает так же, как OracleRANK()
функция, и поэтому является общим (просто подставьте имена таблиц и столбцов).но дело в том, что это тот же код, который может и будет использоваться во время выполнения для создания
Order
столбец, если это было производное значение, а не реальный столбец в базе данных. Итак, еще раз,Order
столбец и весь код, необходимый для его обслуживания, можно удалить.поэтому я также могу дать вам код для получения значения Order или Rank [производного] непосредственно из ваших базовых таблиц, независимо от столбца Order.
После этого присваивание
Order
тривиально. Еще один способ заявить, что я бы заменил ваш первыйSELECT
и выполнять обе функции в одном сегменте кода; нет необходимости вCOUNT()
как отдельный сегмент кода.
Вы заинтересованы?
В каком случае мне нужно знать точное col_N
типы, а что Order
значение основано, например, на высшая студенческая марка. Определение таблицы (запутано) проще.
Ответ на комментарии
- Ну, если это временная таблица, есть гораздо более простой способ, другой подход:
- Дать ему
Order
колонка - определить это как
IDENTITY
- обеспечить
SELECT
вы используете для заполнения имеет правильныйORDER BY
,
- Дать ему
Вам все еще нужно
Order
вычисляется?
Если так, извините, я не знаю, как сделать этот звук более приятным. Я понимаю, что вы думаете, что мне не нужно знать ответ на мой вопрос; но код, который я использую, находится за этим порогом, иначе вы бы уже закодировали его (похоже, у вас есть некоторый опыт работы с SQL и Sybase).Я не "составляю", у меня есть код в течение 20 лет. В каждом случае мне просто нужно подключить конкретные имена таблиц и столбцов, это занимает 10 секунд. Поэтому я знаю, что нужно коду (я понимаю, что логический принцип, который используется в коде, сам код очень прост). И, конечно, есть вариации, потому что это логическое решение, а не просто кусок умного кода: один человек хочет, чтобы ученики были ранжированы Марком; кто-то хочет две колонки со второй
DESCending
,Для объяснения проблемы всегда требуется больше времени, чем для ее устранения.
Например. у вас есть 2 столбца (описание в порядке, спасибо). Но вы просите порядковый номер, который (по определению) требует только один столбец или совокупность. Представьте себе уникальный кластерный индекс на
(col_1, col2)
то, что вы говоритеOrder
необходимо определить. Я не понимаю почемуcol_2
Соответствующий. Если порядковый номер для строки, гдеcol_1
если "KKKKKK" равен 12345, то порядковый номер строки "KKKKKL" должен быть 12346; независимо от того, чтоcol_2
в любом из этих двух рядов. Это ведущий столбец индекса.Код, который я предоставляю, должен принимать все, что вы логически делаете в этом
ORDER BY
пункт во внимание. В противном случае он будет "незаконченным" или "незавершенным", и вам все равно придется возиться с ним; что не будет справедливым по отношению к вам, потому что вы не понимаете логический принцип, стоящий за ним.Тогда у вас есть осложнение из-за использования
VARCHARs
, который легко закодировать, но мне нужно знать, что это такое. Используя мою визуализацию Clustered Index, какая из этих четырех верна? Нужно ли мнеLTRIM()
?( col_1 , col2)
( CONVERT( CHAR(30), col_1 ) , CONVERT( CHAR(30), col_2 ) )
( col_1 + col_2 ) -- as varchars
( CONVERT( CHAR(30), col_1 ) + CONVERT( CHAR(30), col_2 ) )
ура
Надеюсь, что это решение подходит.
Добавить новое поле в таблицу T, например, ID
затем
обновить T set ID = число () из T порядка на Col1, Col2
Не уверен в версии Sybase, которую вы используете, но это работает на 5.5.
Выбор * из T порядка по col1, col2 теперь даст тот же результат, что и выбор * из T порядка по идентификатору
Приветствия AL