如何获取最大列名称

时间:2014-02-09 23:46:47

标签: sql sql-server tsql

这是一个示例表:

Create table #TableA (ID INT
                             , [1] DECIMAL(6,5)
                             ,[1.1] DECIMAL(6,5)
                             , [2] DECIMAL(6,5)
                             ,[2.2] DECIMAL(6,5)
                             , [3] DECIMAL(6,5)
                             ,[3.3] DECIMAL(6,5)
                             , [4] DECIMAL(6,5)
                             ,[4.4] DECIMAL(6,5)
                             , FLAGB1 CHAR(1)
                             , FLAGB2 float)
INSERT INTO #TABLEA (ID, [1],[1.1],[2],[2.2],[3],[3.3],[4],[4.4],FLAGB1,FLAGB2  )
VALUES(1, 1.1111,null, 2.2222,0.1234, 3.3333,null,null, 1.4444,'y',null )
         , (2, null,1.2345, 2.2345,null, 3.2345, 4.2345,1.5437,0.2378,null,null)
         ,(3, 5.3789,1.2222,0.23864,null, 2.2222, 3.2222, 4.2222,null,'y',null)
Drop #TableA

如果FLAGB1为'Y',我需要列FLAGB2来获取“MAX”列名。道歉,我不能更清楚地将要求放在一个句子中,所以结果应该是这样的:

> [ID]  [1]     [1.1]   [2]     [2.2]   [3]     [3.3]   [4]     [4.4]   [FLAGB1]   [FLAGB2]
> 1     1.11110 NULL    2.22220 0.12340 3.33330 NULL    NULL    1.44440  y          4.4
> 2     NULL    1.23450 2.23450 NULL    3.23450 4.23450 1.54370 0.23780  NULL       NULL
> 3     5.37890 1.22220 0.23864 NULL    2.22220 3.22220 4.22220 NULL     y          4

2 个答案:

答案 0 :(得分:1)

不幸的是,SQL Server没有greatest()功能。你可以用case语句来痛苦地做到这一点:

update #tableA
    set flagB2 = (case when [1] >= [1.1] and [1] >= [2] and [1] >= [2.2] and
                            [1] >= [3] and [1] >= [3.3] and [1] >= [4] and [1] >= [4.4]
                       then 1
                       when [2] >= [1] and [2] >= [1.1] and  and [2] >= [2.2] and
                            [2] >= [3] and [2] >= [3.3] and [2] >= [4] and [2] >= [4.4]
                       then 2
                       . . .
                  end)
    where flagB1 = 'y';

这种类型的数据结构让我怀疑列[1] - [4.4]是相关的。这通常意味着您应该有一个关联/联结表,每个id有一行,每个值都有一行。使用该数据结构编写查询会更容易。

答案 1 :(得分:0)

以下内容允许更改表架构。看起来你可以根据你所展示的内容使用一些容差。我带了一个光标,因为我看不到在“原始”更新语句中使用服务器的反射函数。但我认为它改进了对脚本中的列进行硬编码。

CREATE TABLE #TableA (
  ID int PRIMARY KEY,
  [1] DECIMAL(6,5),
  [1.1] DECIMAL(6,5),
  [2] DECIMAL(6,5),
  [2.2] DECIMAL(6,5),
  [3] DECIMAL(6,5),
  [3.3] DECIMAL(6,5),
  [4] DECIMAL(6,5),
  [4.4] DECIMAL(6,5),
  FLAGB1 CHAR(1),
  FLAGB2 float)

INSERT INTO #TABLEA (ID,[1],[1.1],[2],[2.2],[3],[3.3],[4],[4.4],FLAGB1,FLAGB2)
VALUES(1, 1.1111,null, 2.2222,0.1234, 3.3333,null,null, 1.4444,'y',null )
         , (2, null,1.2345, 2.2345,null, 3.2345, 4.2345,1.5437,0.2378,null,null)
         ,(3, 5.3789,1.2222,0.23864,null, 2.2222, 3.2222, 4.2222,null,'y',null)

-- The following will run a separate UPDATE statement for every column having a numeric name on the #TableA temp table

-- Get all column names from the temp table (thus tempdb's INFORMATION_SCHEMA) that are numeric and put them in a new temp table, #columns
SELECT Column_Name
INTO #columns
FROM tempdb.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE '#TableA%'
  AND ISNUMERIC(Column_Name) = 1

DECLARE @column_name varchar(80)

-- Create a cursor to loop through the contents of #columns 
DECLARE cur_columns CURSOR FOR
  SELECT 
    Column_Name 
  FROM 
    #columns 
  ORDER BY 
    CONVERT(decimal, Column_Name)

OPEN cur_columns
FETCH NEXT FROM cur_columns INTO @column_name

-- For each numeric column name...
WHILE(@@FETCH_STATUS = 0)
BEGIN
  DECLARE @SQL varchar(max)

  -- Build an UPDATE statement dynamically
  -- Update the FLAGB2 column with the column name for this iteration given the value in that column is not null and FLAGB1 is either 'y' or 'Y'
  SET @SQL = '
    UPDATE #TableA SET
      FLAGB2 = ' + @column_name + '
    WHERE
      ' + QUOTENAME(@column_name) + ' IS NOT NULL
      AND UPPER(FLAGB1) = ''Y'''

  -- Execute the UPDATE statement
  EXEC(@SQL)

  FETCH NEXT FROM cur_columns INTO @column_name
END

CLOSE cur_columns
DEALLOCATE cur_columns

SELECT * FROM #TableA