Accedere alle colonne di una tabella in base all'indice anziché al nome nella stored procedure di SQL Server
-
28-10-2019 - |
Domanda
Esiste un modo per accedere alle colonne in base al loro indice all'interno di una stored procedure in SQL Server?
Lo scopo è calcolare molte colonne.Stavo leggendo dei cursori, ma non so come applicarli.
Lascia che ti spieghi il mio problema:
Ho una riga del tipo:
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
Devo calcolare qualcosa come (field_1*field1) - (Sfield_1* Sfiled_1) / more...
Quindi 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 valutando la possibilità di creare SQL dinamico, ottenere i nomi delle colonne in una stringa e suddividere quelli di cui ho bisogno, ma questo approccio rende il problema più difficile.Pensavo che ottenere il numero di colonna in base all'indice potesse semplificarti la vita.
Soluzione
Innanzitutto, come affermato da OMG Ponies , non puoi fare riferimento alle colonne in base alla loro posizione ordinale.Questo non è un incidente.La specifica SQL non è creata per lo schema dinamico né in DDL né in DML.
Detto questo, mi chiedo perché hai i tuoi dati strutturati come fai.Un segno di una mancata corrispondenza tra lo schema e il dominio problematico si genera quando si tenta di estrarre le informazioni.Quando le query sono incredibilmente complicate da scrivere, è un'indicazione che lo schema non modella correttamente il dominio per il quale è stato progettato.
Comunque sia, dato quello che ci hai detto, una soluzione alternativa sarebbe qualcosa del genere: (presumo che field_1*field1
fosse pensato per essere field_1 * field_1
o field_1
squared 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 tua query avrà il seguente aspetto:
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
Altri suggerimenti
No, non è possibile utilizzare la posizione ordinale (numerica) nella clausola SELECT
.
Solo nella clausola ORDER BY
è possibile utilizzare la posizione ordinale, perché si basa sulle colonne specificate nella clausola SELECT
.
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 di cui ho bisogno per analizzare 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)