2

order我有一个表 T (下面的结构),它最初在一个整数列中包含全 NULL 值:

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 的行计数),它分配order值以便SELECT * FROM T ORDER BY order返回与上述查询 100% 相同的行顺序。

查询不一定需要就地更新表 T,如果这样可以使查询更简单,我可以创建表 T2 的副本。

NOTE1:解决方案必须是真正的查询或一组查询,涉及循环或游标。

注意 2:假设数据是唯一可根据上述 order by 排序的 - 无需担心 2 行可以随机分配相同的 order 的情况。

注意 3:我更喜欢通用解决方案,但如果您想要一个特定的排序表达式示例,可以说:

从 T 中选择 *
按大小写排序 WHEN col1="" THEN "AAAAAA" ELSE col1 END, ISNULL(col2, "ZZZ")
4

3 回答 3

4

我以 pubs2 中的 roysched 表为例。我添加了一个列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 与上述 order by 返回的行的顺序相匹配

于 2010-05-13T15:39:11.693 回答
1

DVK

人们已经回答了您的具体问题,而您选择了答案。

但整个问题还有一个更深层次的问题。

  1. 据我了解,Order是表中的一列;它标识要呈现(或类似)行的顺序。那是对的吗 ?

  2. 如果是这样,那么该表被大量非规范化:您已经破坏了 3NF(功能依赖规则被破坏);您在列中有派生值(重复信息);引入了更新异常(当您更新一列中的数据时,您现在需要更新另一列中重复的[依赖]数据)。

  3. 其中最重要的当然是更新异常。您不能再在(现在是非关系的、非规范化的)表中插入一行。对于每个插入,您必须重新计算和更新表Order中至少一个且最多每隔一行的列。

  4. 这些都不是必需的。

    • 我只能在您的问题范围内回答您的问题,以填充该Order列(由不断维护它的代码段调用)。所需的代码是 5 行。基表上的纯标准 SQL。没有意见。没有临时表。没有循环或游标。工作原理与 OracleRANK()函数相同,因此是通用的(只需替换您的表和列名)。

    • Order但关键是,如果它是派生值,而不是数据库中的真实列,则可以并且将在运行时使用相同的代码来生成列。同样,可以删除该Order列以及维护它所需的所有代码。

    • 因此,我不妨为您提供直接从您的基表中生成 Order 或 Rank [派生] 值的代码,而不考虑 Order 列。

  5. 之后,分配Order是微不足道的。另一种说法是,我将替换您的第一个SELECT,并在一个代码段中执行这两个功能;不需要COUNT()作为单独的代码段。

你感兴趣吗 ?

在这种情况下,我需要知道确切的col_N类型,以及Order值的基础,例如。学生最高分。表定义(混淆)更容易。

回应评论

  1. 好吧,如果它是一个临时表,有一种更简单的方法,一种不同的方法:
    • 给它一个Order专栏
    • 将其定义为IDENTITY
    • 确保SELECT您用来填充它的ORDER BY
      .
  2. 你还需要Order计算吗?
    如果是这样,请原谅我,我不知道如何让这听起来更好听。我知道你认为 我不需要知道我的问题的答案;但是我使用的代码超出了那个阈值,否则你现在已经编码了(你似乎有一些 SQL 和 Sybase 的经验)。

    我不是“起草”,我已经有 20 年的代码了。在每种情况下,我只需要插入特定的表和列名,需要 10 秒。因此,我确实知道代码需要什么(例如,我了解代码使用的逻辑原理,代码本身非常简单)。当然也有变化,因为这是一个合乎逻辑的解决方案,而不仅仅是一段聪明的代码:一个人希望学生按 Mark 排名;其他人想要两列和第二列DESCending

    • 解释问题总是比解决问题需要更长的时间。

    • 例如。你有 2 列(描述很好,谢谢)。但是您要的是一个序数,它(根据定义)只需要一个列或聚合。想象一下 上的唯一聚集索引(col_1, col2),这就是您所说的Order需要识别的内容。我不明白为什么是col_2相关的。如果“KKKKKK”所在行col_1的序号为 12345,则“KKKKKL”所在行的序号必须为 12346;不管是什么col_2,在这两行中的任何一个。它是索引的前导列。

    • 我提供的代码必须考虑到您在该子句中逻辑上所做的任何事情。ORDER BY否则就是“未完成”或“不完整”,还得乱来;这对您不公平,因为您不了解其背后的逻辑原理。

    • 然后你有由于使用的复杂性VARCHARs,这很容易编码,但我需要知道它是什么。使用我的聚集索引可视化,这四个中哪一个是正确的?我需要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 ) )

干杯

于 2010-12-14T00:45:25.177 回答
0

希望这个解决方案是合适的。

向表 T 添加一个新字段,例如 ID

然后

通过 Col1、Col2 从 T 顺序更新 T 集 ID = number()

不确定您使用的 Sybase 版本,但这适用于 5.5。

select * from T order by col1, col2 现在将给出与 select * from T order by ID 相同的结果

干杯

于 2010-12-10T04:41:44.547 回答