2011-02-03 9 views
6

Esiste un modo per accedere alle colonne in base al loro indice all'interno di una stored procedure in SQL Server?Accedere alle colonne di una tabella per indice anziché per nome nella stored procedure di SQL Server

Lo scopo è calcolare un sacco di colonne. Stavo leggendo di cursori, ma non so come applicarli.

Mi spiego il mio problema:

Ho fila come:

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 

ho bisogno di calcolare qualcosa come (field_1*field1) - (Sfield_1* Sfiled_1)/more...

Così il risultato viene memorizzato in una colonna della tabella d volte.

Quindi il risultato è una tabella d column * d row.

Poiché il numero di colonne è variabile, stavo prendendo in considerazione l'idea di creare SQL dinamico, ottenere i nomi di colonne in una stringa e dividere quelli di cui ho bisogno, ma questo approccio rende il problema più difficile. Pensavo che ottenere il numero di colonne per indice potesse semplificarci la vita.

+1

Possibile duplicato [E 'possibile selezionare i dati di SQL Server utilizzando colonna posizione ordinale] (http://stackoverflow.com/questions/368505/is-it-possible-to-select-sql-server- data-using-column-ordinal-position) –

risposta

3

Innanzitutto, come indicato in OMG Ponies, non è possibile fare riferimento alle colonne in base alla loro posizione ordinale. Questo non è un incidente. La specifica SQL non è costruita per uno schema dinamico in DDL o DML.

Dato ciò, devo chiedermi perché i tuoi dati sono strutturati come te. Un segno di una mancata corrispondenza tra lo schema e il dominio del problema si impenna quando si tenta di estrarre informazioni. Quando le query sono incredibilmente ingombranti da scrivere, è un'indicazione che lo schema non modella correttamente il dominio per cui è stato progettato.

Tuttavia, sia come sia, dato quello che ci avete detto, una soluzione alternativa sarebbe qualcosa di simile al seguente: (Sto assumendo che field_1*field1 voleva essere field_1 * field_1 o field_1 al quadrato o 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 

Ora la ricerca si presenta come:

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 
+0

Grazie, ho una tabella in questo modo perché è stata generata da una query più lunga che restituisce una singola riga con colonne D * N, Ora devo prendere alcune colonne e fare alcune operazioni, Come faccio ad usare il codice che hai fornito in la mia procedura di archiviazione ?, Poiché ci sono più field_x ... Sto trhinking in sql dinamico ... Come @template = Sequence, campo_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], in una stringa, e quindi sostituisce dinamicamente nel codice che hai fornito. Come posso farlo?, Potresti spiegarmi un po 'il codice? Grazie – cMinor

+0

@darkcminor - In primo luogo, vorrei esaminare l'origine della query più lunga con le colonne D * N e vedere se i dati grezzi sono strutturati in questo modo. Forse viene assemblato in questo modo da una struttura normalizzata. Se così fosse, allora ovviamente usare la struttura normalizzata sarebbe più facile. In secondo luogo, la chiave per la soluzione è la query "Unione tutti". Dividi l'elenco di colonne in un'istruzione Select per 'N' e aggiungi una sequenza. Quindi, dato ciò che hai presentato nel tuo post, userei qualcosa di diverso da T-SQL per analizzare la stringa nella query Union All. Una volta ottenuto ciò, la query dovrebbe essere più semplice. – Thomas

6

No, non è possibile utilizzare la posizione ordinale (numerico) nella clausola SELECT.

Solo nella clausola ORDER BY è possibile utilizzare la posizione ordinale, poiché si basa sulla colonna (s) specificata nella clausola SELECT.

+0

come sarebbe l'aproach, per risolvere il problema? – cMinor

+0

@darkcminor: riferimento alle colonne per nome. Usa SQL dinamico per ottenere un elenco di nomi di colonne se lo desideri, ma l'ordine delle colonne è irrilevante per un database. Ho dimenticato di menzionare che alcuni database supportano gli ordinali in GROUP BY e HAVING. L'altra alternativa è ridisegnare le colonne per supportare le tue esigenze. –

+0

Ho provato SELEZIONA @column \t = COALESCE (@ colonna + '', '') \t \t \t \t \t \t \t + COLUMN_NAME DA INFORMATION_SCHEMA.COLUMNS \t WHERE (TABLE_NAME = 'TEMP') che mi dà i nomi separati da ',' ma come ho detto, dividere e ottenere i valori di diverse colonne è sempre più difficile, potrebbe essere possibile utilizzare il pivot o qualcosa del genere? – cMinor

0

questo potrebbe non essere il più elegante o efficiente ma funziona. Lo sto usando per creare una nuova tabella per mappature più veloci tra i dati che ho bisogno di analizzare attraverso tutte le colonne/righe.

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) 
Problemi correlati