Как правильно назначать порядковые номера порядковым строкам в таблице в Sybase? - PullRequest
2 голосов
/ 12 мая 2010

У меня есть таблица T (структура ниже), которая изначально содержит все NULL-значения в целом столбце order:

col1  varchar(30),
col2  varchar(30),
order int NULL

У меня также есть способ заказать столбцы "colN", например,

SELECT * FROM T ORDER BY some_expression_involving_col1_and_col2

Каков наилучший способ присвоения - IN SQL - числовых значений порядка 1-N для таблицы порядка, чтобы значения порядка соответствовали порядку строк, возвращаемых приведенным выше ORDER BY ?

Другими словами, я хотел бы один запрос (синтаксис Sybase SQL, поэтому не указывается число строк в Oracle), который присваивает значения order, чтобы SELECT * FROM T ORDER BY order возвращал 100% порядок строк, аналогичный приведенному выше запросу.

Запрос НЕ обязательно должен обновлять таблицу T на месте, я согласен с созданием копии таблицы T2, если это упростит запрос.

ПРИМЕЧАНИЕ 1. Решением должен быть реальный запрос или набор запросов, , а не с использованием цикла или курсора.

ПРИМЕЧАНИЕ 2. Предположим, что данные могут быть однозначно упорядочены в соответствии с приведенным выше порядком - не нужно беспокоиться о ситуации, когда 2 строкам можно назначить один и тот же порядок случайным образом.

ПРИМЕЧАНИЕ 3. Я бы предпочел универсальное решение, но если вы хотите конкретный пример выражения порядка, скажем:

SELECT * FROM T 
ORDER BY CASE WHEN col1="" THEN "AAAAAA" ELSE col1 END, ISNULL(col2, "ZZZ")

Ответы [ 3 ]

4 голосов
/ 13 мая 2010

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

1 голос
/ 14 декабря 2010

ДВК

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

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

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

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

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

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

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

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

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

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

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

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

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

  1. Ну, если это временная таблица, есть гораздо более простой способ, другой подход:
    • Дайте ему Order столбец
    • определить его как IDENTITY
    • убедитесь, что SELECT, который вы используете для заполнения, имеет правильный ORDER BY
      .
  2. Вам все еще нужно вычислить Order?
    Если так, извините, я не знаю, как сделать этот звук более приятным. Я понимаю, что вы думаете Мне не нужно знать ответ на мой вопрос; но код, который я использую, превышает этот порог , иначе вы бы уже закодировали его (похоже, у вас есть некоторый опыт работы с SQL и Sybase).

    Я не "пишу", у меня есть код в течение 20 лет. В каждом случае мне просто нужно подключить конкретные имена таблиц и столбцов, это занимает 10 секунд. Поэтому я знаю, что нужно коду (как я понимаю, логический принцип, который использует код, сам код очень прост). И, конечно, есть вариации, потому что это логическое решение, а не просто кусок умного кода: один человек хочет, чтобы ученики были ранжированы Марком; кто-то хочет две колонки со второй DESCending.

    • Для объяснения проблемы всегда требуется больше времени, чем для ее устранения.

    • Eg. у вас есть 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 ) )

Приветствия

0 голосов
/ 10 декабря 2010

Надеюсь, что это решение подходит.

Добавить новое поле в таблицу T, например, ID

Тогда

обновить T set ID = число () из T порядка на Col1, Col2

Не уверен, какую версию Sybase вы используете, но это работает на 5.5.

Выбор * из T порядка по col1, col2 теперь даст тот же результат, что и выберите * из T заказа по ID

Приветствие AL

...