¿Cómo declarar una matriz dentro del procedimiento almacenado de MS SQL Server?

85

Necesito declarar 12 variables decimales, correspondientes al año de cada mes, con un cursor sumo valores a estas variables, luego actualizo alguna información de ventas.

No sé si el servidor SQL tiene esta sintaxis

 Declare MonthsSale(1 to 12) as decimal(18,2)

Este código funciona bien. !

CREATE PROCEDURE [dbo].[proc_test]
AS
BEGIN

--SET NOCOUNT ON;

DECLARE @monthsales TABLE ( monthnr int,    amount decimal(18,2)    )


-- PUT YOUR OWN CODE HERE


-- THIS IS TEST CODE
-- 1 REPRESENTS JANUARY, ...
INSERT @monthsales (monthnr, amount) VALUES (1, 100)
INSERT @monthsales (monthnr, amount) VALUES (1, 100)

INSERT @monthsales (monthnr, amount) VALUES (2, 200)
INSERT @monthsales (monthnr, amount) VALUES (3, 300)
INSERT @monthsales (monthnr, amount) VALUES (4, 400)
INSERT @monthsales (monthnr, amount) VALUES (5, 500)
INSERT @monthsales (monthnr, amount) VALUES (6, 600)
INSERT @monthsales (monthnr, amount) VALUES (7, 700)
INSERT @monthsales (monthnr, amount) VALUES (8, 800)
INSERT @monthsales (monthnr, amount) VALUES (9, 900)
INSERT @monthsales (monthnr, amount) VALUES (10, 1000)
INSERT @monthsales (monthnr, amount) VALUES (11, 1100)
INSERT @monthsales (monthnr, amount) VALUES (12, 1200)


SELECT monthnr, SUM(amount) AS SUM_MONTH_1 FROM @monthsales WHERE monthnr = 1 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_2 FROM @monthsales WHERE monthnr = 2 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_3 FROM @monthsales WHERE monthnr = 3 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_4 FROM @monthsales WHERE monthnr = 4 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_5 FROM @monthsales WHERE monthnr = 5 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_6 FROM @monthsales WHERE monthnr = 6 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_7 FROM @monthsales WHERE monthnr = 7 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_8 FROM @monthsales WHERE monthnr = 8 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_9 FROM @monthsales WHERE monthnr = 9 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_10 FROM @monthsales WHERE monthnr = 10 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_11 FROM @monthsales WHERE monthnr = 11 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_12 FROM @monthsales WHERE monthnr = 12 GROUP BY monthnr

-- END TEST CODE
END
Ricardo Balda
fuente

Respuestas:

143

Podría declarar una variable de tabla (Declarar una variable de tipo tabla):

declare @MonthsSale table(monthnr int)
insert into @MonthsSale (monthnr) values (1)
insert into @MonthsSale (monthnr) values (2)
....

Puede agregar columnas adicionales como desee:

declare @MonthsSale table(monthnr int, totalsales tinyint)

Puede actualizar la variable de la tabla como cualquier otra tabla:

update m
set m.TotalSales = sum(s.SalesValue)
from @MonthsSale m
left join Sales s on month(s.SalesDt) = m.MonthNr
Andomar
fuente
26

¿Hay alguna razón por la que no está utilizando una variable de tabla y el operador SUM agregado, en lugar de un cursor? SQL sobresale en operaciones orientadas a conjuntos. El 99,87% de las veces que te encuentras usando un cursor, hay una alternativa orientada a conjuntos que es más eficiente:

declare @MonthsSale table
(
MonthNumber int,
MonthName varchar(9),
MonthSale decimal(18,2)
)

insert into @MonthsSale
select
    1, 'January', 100.00
union select    
    2, 'February', 200.00
union select    
    3, 'March', 300.00
union select    
    4, 'April', 400.00
union select    
    5, 'May', 500.00
union select    
    6, 'June', 600.00
union select    
    7, 'July', 700.00
union select    
    8, 'August', 800.00
union select    
    9, 'September', 900.00
union select    
    10, 'October', 1000.00
union select    
    11, 'November', 1100.00
union select    
    12, 'December', 1200.00

select * from @MonthsSale   
select SUM(MonthSale) as [TotalSales] from @MonthsSale
Paul Smith
fuente
12
Al parecer, en MSSQL2012 ahora puede insertar en este formato: VALUES (1, 'January', 100.00), (2, 'February', 200.00) - fuente: blog.sqlauthority.com/2012/10/27/…
andrewb
3
Esta característica escapó totalmente a mi conocimiento; aparentemente eso también funciona en SQL 2008.
Paul Smith
8

T-SQL no admite matrices que yo sepa.

¿Cuál es la estructura de tu mesa? Probablemente podría diseñar una consulta que haga esto en su lugar:

select
month,
sum(sales)
from sales_table
group by month
order by month
Patrick Burleson
fuente
Solo como comentario lateral, señalaría que la sintaxis T [n] .v es un poco más concisa que (seleccione v de T donde Ti = n). De hecho, es mucho más conciso. Me gustaría mucho ver a T-SQL agregarlo.
debatidor
3

Gran pregunta y gran idea, pero en SQL deberá hacer esto:

Para el tipo de datos datetime, algo como esto:

declare @BeginDate    datetime = '1/1/2016',
        @EndDate      datetime = '12/1/2016'
create table #months (dates datetime)
declare @var datetime = @BeginDate
   while @var < dateadd(MONTH, +1, @EndDate)
   Begin
          insert into #months Values(@var)
          set @var = Dateadd(MONTH, +1, @var)
   end

Si todo lo que realmente quieres son números, haz esto:

create table #numbas (digit int)
declare @var int = 1        --your starting digit
    while @var <= 12        --your ending digit
    begin
        insert into #numbas Values(@var)
        set @var = @var +1
    end
Dane Thomas
fuente