如何在while函数中增加列序号位置?

时间:2017-02-28 10:14:28

标签: sql sql-server tsql

摘要:我有一个包含多列的表,我正在尝试对所有列实现while(循环)函数,以提取每列的平均值。

编码这会将一个数字归于每一列(以减少增量方法的可能性)

Declare @tablename as varchar(128)
Declare @column1 as varchar(128)
Delect @tablename = 'MOMENTUM_Results'

Select @column1 = sc.name
from sysobjects as so inner join syscolumns as sc on so.id = sc.id 
where so.name = @tablename and sc.colid = 2

当我打印此代码时,它会根据我从1到122的数字打印列的名称。

循环函数的代码:

WHILE ....
BEGIN
SET @SQL = 'SELECT AVG(MR.[' + @column1 + ']) From MOMENTUM_Quintile MQ 
Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + @column1 + '] = 1'
END

但我绝对不知道如何将这个函数集成到循环中,所以函数逐个遍历所有列,因此寻找一些建议..

谢谢!

R.H。

enter image description here

enter image description here

3 个答案:

答案 0 :(得分:1)

  1. 首先将该表中的所有列名称放入临时表(#temp)
  2. 获取该临时表中所有列(@count_of_columns)的计数。
  3. 声明变量@count = 1
  4. 将while循环声明为While(@ count< = @ count_of_columns)
  5. - >使用以下查询

    在此while循环内一个接一个地获取列名称
    SET @column1=(select top 1 column1 from 
    (select Row_number()over (order by column1) as r_n_n, column1                  
    from #temp) aa 
    where r_n_n >=@Count)
    

    - >在这里使用您的实际代码

    - >增加@count变量

    set @count = @count + 1
    

答案 1 :(得分:1)

你能不能只是将public function set_service_status() { $status = $this->input->post('status'); $change_by = $this->input->post('change_by'); $date_time = $this->input->post('date_time'); $message = $this->input->post('message'); $data= array( 'status' => $status, 'status_change_by' => $change_by, 'status_change_date' => $date_time, 'status_message' => $message, ); $this->db->where('name',$pliname); $this->db->update('update_service',$data); } SELECT移到sys.Columns循环的正文中,以获得你之后的那个?像这样......

WHILE

也许我没有正确理解您的问题,但如果您已经写完所有内容,则可以更改展示位置以选择所需的列名称。

当然,您还可以添加其他条件,以确保您按名称或其他方式获取匹配的列或列...

修改

您询问是否将结果查询插入表中。如果您已经有一个表已准备好接收查询的列,那么答案很简单......在DECLARE @TABLENAME AS VARCHAR(128); DECLARE @COLUMN1 AS VARCHAR(128); DECLARE @COUNTER INT; SET @TABLENAME = 'MOMENTUM_Results'; SET @COUNTER = 1; WHILE .... BEGIN SELECT @COLUMN1 = C.Name FROM sys.Columns C WHERE OBJECT_NAME(C.object_id) = @TABLENAME AND C.column_id = @COUNTER ; SET @SQL = 'SELECT AVG(MR.[' + @COLUMN1 + ']) From MOMENTUM_Quintile MQ Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + @COLUMN1 + '] = 1'; ... Other Stuff ... SET @COUNTER = @COUNTER + 1; END ; 循环的主体中,在检索所需的查询后,只需添加WHILE命令:

INSERT

如果你需要创建表,你可以在脚本的头部做这个,然后再声明其他内容,并在WHILE .... BEGIN SELECT @COLUMN1 = C.Name FROM sys.Columns C WHERE OBJECT_NAME(C.object_id) = @TABLENAME AND C.column_id = @COUNTER ; SET @SQL = 'SELECT AVG(MR.[' + @COLUMN1 + ']) From MOMENTUM_Quintile MQ Left Join MOMENTUM_Returns MR on MQ.Mnemonic = MR.Mnemonic WHERE MQ.[' + @COLUMN1 + '] = 1'; INSERT INTO <mytable> (<querycolumn>) VALUES (@SQL); ... Other Stuff ... SET @COUNTER = @COUNTER + 1; 期间做同样的事情:

WHILE

答案 2 :(得分:0)

如果可以避免使用循环或游标,请不要使用循环或游标。程序性思维的魔鬼正在使你远离基于集合的方法,直至痛苦和苦难!

  

我事先知道列名,我只是为了简化我遍历每一列的方式

不!这不是缓解方式,而是惩罚糟糕的引擎: - )

这是你要找的吗?

CREATE TABLE dbo.Test(ID INT, VAl1 DECIMAL(14,4), Val2 DECIMAL(14,4), Val3 DECIMAL(14,4));
GO
INSERT INTO dbo.Test VALUES(1,1,10,100),(2,2,20,200),(3,3,30,300);
GO
    SELECT AVG(Val1) AS Avg1,AVG(Val2) AS Avg2,AVG(Val3) AS Avg3
    FROM dbo.Test;
GO
DROP TABLE dbo.Test;

结果

Avg1        Avg2        Avg3
2.000000    20.000000   200.000000

更新

如果你只是想懒惰并避免打字,你可以尝试这样的事情:

SELECT ',AVG(' + COLUMN_NAME + ') AS ' + QUOTENAME('AVG_' + COLUMN_NAME)   
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_SCHEMA='dbo' AND TABLE_NAME='Test'
FOR XML PATH('')

结果

,AVG(ID) AS [AVG_ID],AVG(VAl1) AS [AVG_VAl1],AVG(Val2) AS [AVG_Val2],AVG(Val3) AS [AVG_Val3]

通过这个技巧,您可以非常轻松地构建硬编码语句: - )