【问题标题】:Access columns of a table by index instead of name in SQL Server stored procedure在 SQL Server 存储过程中通过索引而不是名称访问表的列
【发布时间】:2011-06-20 10:47:57
【问题描述】:

有没有办法在 SQL Server 的存储过程中通过索引来访问列?

目的是计算大量列。我正在阅读有关游标的内容,但我不知道如何应用它们。

让我解释一下我的问题:

我有一排像:

field_1 field_2 field_3 field_4 ...field_d  Sfield_1 Sfield_2 Sfield_3...Sfield_n
1       2       3       4          d        10       20       30         n

我需要计算类似(field_1*field1) - (Sfield_1* Sfiled_1) / more...

所以结果存储在一个表列d次。

所以结果是d column * d row 表。

由于列数是可变的,我正在考虑制作动态 SQL,获取字符串中的列名并拆分我需要的列名,但这种方法使问题变得更加困难。我认为通过索引获取列号可以让生活更轻松。

【问题讨论】:

标签: sql sql-server tsql sql-server-2008 ordinal


【解决方案1】:

不,您不能在SELECT 子句中使用序数(数字)位置。

只有在ORDER BY 子句中才能使用序号位置,因为它基于SELECT 子句中指定的列。

【讨论】:

  • @darkcminor:按名称引用列。如果您愿意,可以使用动态 SQL 获取列名列表,但列顺序与数据库无关。我忘了提到一些数据库确实支持 GROUP BY 和 HAVING 中的序数。另一种选择是重新设计列以满足您的需求。
  • 我已经尝试过 SELECT @column = COALESCE(@column+ ',', '') +COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE(TABLE_NAME = 'TEMP' ),它给了我用 ',' 分隔的名称但正如我所说,拆分并获取几列的值变得越来越难,使用 pivot 或类似的东西是否可行?
  • @darkcminor:这确实是一个不同的问题,common one - see this for an alternative
  • 不是真的,我已经完成了拆分,但是,我正在寻找一种更简单的方法,这就是为什么我认为按索引访问列,有什么想法吗?谢谢
【解决方案2】:

首先,正如OMG Ponies 所说,您不能按顺序位置引用列。这不是意外。 SQL 规范不是为 DDL 或 DML 中的动态模式构建的。

鉴于此,我不得不想知道为什么您的数据要像现在这样结构化。当您尝试提取信息时,模式和问题域之间不匹配的迹象就会出现。当查询编写起来非常麻烦时,这表明模式没有正确地建模它所设计的域。

但是,尽管如此,根据您告诉我们的情况,替代解决方案将类似于以下内容:(我假设 field_1*field1 应该是 field_1 * field_1field_1 平方或Power( field_1, 2 ))

Select 1 As Sequence, field_1 As [Field], Sfield_1 As [SField], Sfiled_1 As [SFiled]
Union All Select 2, field_2, Sfield_2, Sfiled_2
...
Union All Select n, field_n, Sfield_n, Sfiled_n

现在您的查询如下所示:

With Inputs As
    (
    Select 1 As Sequence, field_1 As [Field], Sfield_1 As [SField], Sfiled_1 As [SFiled]
    Union All Select 2, field_2, Sfield_2, Sfiled_2
    ....
    )
    ,  Results As
    (
    Select Case
            When Sequence = 1 Then Power( [Field], 2 ) - ( [SField] * [SFiled] ) 
            Else 1 / Power( [Field], 2 ) - ( [SField] * [SFiled] ) 
            End
            As Result
    From Inputs
    )
Select Exp( Sum( Log( Result ) ) )
From Results

【讨论】:

  • 谢谢,我有一个这样的表,因为它是由一个较长的查询生成的,该查询返回具有 D*N 列的单行,现在我必须取一些列并进行一些操作,我该怎么做使用您在我的存储过程中提供的代码?,因为有更多 field_x...我在动态 sql 中进行调整...就像@template = Sequence,field_1 As [Field],field_2 AS [Field2],... , field_d AS [Fieldd], Sfield_1 As [SField], Sfied_2 As [SField_2],...,Sfield_n As [SField_n], 在一个字符串中,然后在您提供的代码中动态替换。我该怎么做?,你能解释一下,有点代码吗?谢谢
  • @darkcminor - 首先,我将查看具有 D*N 列的较长查询的来源,看看原始数据是否以这种方式构造。也许它是从一个规范化的结构中以这种方式组装起来的。如果是这样的话,那么显然使用归一化结构会更容易。二、解决的关键是Union All查询。根据N 将列列表拆分为一个 Select 语句并添加一个序列。因此,鉴于您在帖子中介绍的内容,我将使用 T-SQL 以外的其他方法将字符串解析为 Union All 查询。一旦你有了它,查询应该会更容易。
【解决方案3】:

这可能不是最优雅或最有效的,但它确实有效。我正在使用它来创建一个新表,以便在需要解析所有列/行的数据之间进行更快的映射。

DECLARE @sqlCommand varchar(1000)
DECLARE @columnNames TABLE (colName varchar(64), colIndex int)
DECLARE @TableName varchar(64) = 'YOURTABLE' --Table Name
DECLARE @rowNumber int = 2 -- y axis
DECLARE @colNumber int = 24 -- x axis

DECLARE @myColumnToOrderBy varchar(64) = 'ID' --use primary key

--Store column names in a temp table
INSERT INTO @columnNames (colName, colIndex)
SELECT COL.name AS ColumnName, ROW_NUMBER() OVER (ORDER BY (SELECT 1))
    FROM sys.tables AS TAB
    INNER JOIN sys.columns AS COL ON COL.object_id = TAB.object_id
    WHERE TAB.name = @TableName
    ORDER BY COL.column_id;

DECLARE @colName varchar(64)
SELECT @colName = colName FROM @columnNames WHERE colIndex = @colNumber

--Create Dynamic Query to retrieve the x,y coordinates from table
SET @sqlCommand = 'SELECT ' + @colName + ' FROM (SELECT ' + @colName + ', ROW_NUMBER() OVER (ORDER BY ' + @myColumnToOrderBy+ ') AS RowNum FROM ' + @tableName + ') t2 WHERE RowNum = ' + CAST(@rowNumber AS varchar(5))
EXEC(@sqlCommand)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多