Как правильно назначить порядковые номера упорядоченным строкам в таблице в 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

Люди ответили на ваш конкретный вопрос, и вы выбрали ответ.

Но у всего вопроса есть более глубокая проблема.

  1. Из того, что я могу понять, Order столбец в таблице; который определяет Порядок, в котором должны быть представлены строки (или аналогичные). Это верно?

  2. Если это так, то таблица в значительной степени денормализована: вы нарушили 3NF (правило функциональной зависимости нарушено); у вас есть производное значение в столбце (дублированная информация); введены аномалии обновления (когда вы обновляете данные в столбце, теперь вам нужно обновить дублированные [зависимые] данные в другом столбце).

  3. Самым важным из них, конечно же, являются аномалии обновления. Вы больше не можете вставлять строку в (теперь нереляционную, ненормализованную) таблицу. Для каждой вставки вы должны пересчитать и обновить Order столбец, по крайней мере, для одной и не более, для каждой второй строки в таблице.

  4. Ничего из этого не нужно.

    • Я мог бы ответить на ваш вопрос только в рамках вашего вопроса, чтобы заполнить Order столбец (вызывается сегментом кода, который постоянно поддерживает его). Требуемый код состоит из 5 строк. Чистый стандартный SQL на базовой таблице. Нет просмотров. Нет временных таблиц. Никаких петель или курсоров. Работает так же, как Oracle RANK() функция, и поэтому является общим (просто подставьте имена таблиц и столбцов).

    • но дело в том, что это тот же код, который может и будет использоваться во время выполнения для создания Order столбец, если это было производное значение, а не реальный столбец в базе данных. Итак, еще раз, Order столбец и весь код, необходимый для его обслуживания, можно удалить.

    • поэтому я также могу дать вам код для получения значения Order или Rank [производного] непосредственно из ваших базовых таблиц, независимо от столбца Order.

  5. После этого присваивание Order тривиально. Еще один способ заявить, что я бы заменил ваш первый SELECT и выполнять обе функции в одном сегменте кода; нет необходимости в COUNT() как отдельный сегмент кода.

Вы заинтересованы?

В каком случае мне нужно знать точное col_N типы, а что Order значение основано, например, на высшая студенческая марка. Определение таблицы (запутано) проще.

Ответ на комментарии

  1. Ну, если это временная таблица, есть гораздо более простой способ, другой подход:
    • Дать ему Order колонка
    • определить это как IDENTITY
    • обеспечить SELECT вы используете для заполнения имеет правильный ORDER BY
      ,
  2. Вам все еще нужно 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

Другие вопросы по тегам