Инициализация переменных таблицы TSQL
У меня есть следующая переменная таблицы TSQL:
declare @NumDaysMonth table
(
month_id smallint,
num_days smallint
)
Я просто хочу быстро найти количество дней в каждом месяце. Как я могу инициализировать эту таблицу как массив C:
int numDaysMonth[] = {31, 28, 30, ... , 31};
Ответы
Ответ 1
Ну, ты не можешь. Лучшее, что вы можете сделать, это что-то вроде этого
Insert Into @NumDaysMonth
Values
(1,31),
(2,28),
(3,31),
...
(12,31);
Тогда поиск может быть чем-то вроде
DECLARE @LookItUp int
SELECT @LookItUp = num_days
FROM @NumDaysMonth
WHERE month_Id = 12;
PRINT @LookItUp
Демо-версия SQL Fiddle
Ответ 2
Ниже не рассматривается вопрос об инициализации таблицы OP. Вы можете рассматривать его как форматированный комментарий.
Трюк, который удобен для нечетной таблицы поиска, заключается в создании виртуальной таблицы "на лету":
declare @Foo as Table ( Month Int )
insert into @Foo values ( 1 ), ( 3 ), ( 9 )
select *
from @Foo as F inner join
( select month_id, num_days
from ( values
( 1, 31 ), ( 2, 28 ), ( 3, 31 ), ( 4, 30 ), ( 5, 31 ), ( 6, 30 ),
( 7, 31 ), ( 8, 31 ), ( 9, 30 ), ( 10, 31 ), ( 11, 30 ), ( 12, 31 )
) as NumDaysMonth( month_id, num_days ) ) as NumDaysMonth on
NumDaysMonth.month_id = F.Month
Для получения количества дней в месяц я был бы более склонен создавать функцию, которая принимает год и месяц и возвращает правильное значение. Когда мне нужен быстрый переход от некоторого кода к чему-то читаемому, удобная таблица.
Если вам нужно обращаться к таблице faux несколько раз в одном месте:
; with NumDaysMonth as (
( select month_id, num_days
from ( values
( 1, 31 ), ( 2, 28 ), ( 3, 31 ), ( 4, 30 ), ( 5, 31 ), ( 6, 30 ),
( 7, 31 ), ( 8, 31 ), ( 9, 30 ), ( 10, 31 ), ( 11, 30 ), ( 12, 31 )
) as NumDaysMonth( month_id, num_days ) ) ),
FooMonths as (
select *
from @Foo as F inner join
NumDaysMonth as NDM on NDM.month_id = F.Month ),
FooWithFollowingMonths as (
select *
from FooMonths
union
select *
from @Foo as F inner join
NumDaysMonth as NDM on NDM.month_id = F.Month + 1 )
select *
from FooWithFollowingMonths
Кроме того, таблица поиска, вероятно, должна храниться как реальная функция таблицы или таблицы.
Ответ 3
FYI, что тип массива немного неполный, поскольку он не меняется с високосными годами? например в феврале этого года 29 дней.
Ниже приведен список, который является 0-индексированным (например, С#) и относится к текущему году.
declare @NumDaysMonth table
(
month_id smallint,
num_days smallint
)
insert @NumDaysMonth
select m.m, day(dateadd(m,m+1,y)-1)
from
(select CAST(right(year(getdate()),4)+'0101' as datetime)) y(y)
cross join
(select 0 union all
select 1 union all
select 2 union all
select 3 union all
select 4 union all
select 5 union all
select 6 union all
select 7 union all
select 8 union all
select 9 union all
select 10 union all
select 11) m(m)
select * from @NumDaysMonth
-- results
MONTH_ID NUM_DAYS
0 31
1 29
2 31
3 30
4 31
5 30
6 31
7 31
8 30
9 31
10 30
11 31
Если вам это нужно в течение любого другого года, введите год в подзапрос Y, например. (select cast('19990101' as datetime))
Ответ 4
Это легко. Используйте identity
для генерации автоматически увеличивающегося числа.
declare @NumDaysMonth table
(
month_id smallint identity primary key,
num_days smallint
);
insert into @NumDaysMonth
(num_days)
values
(31),
(28),
(31),
(30),
(31),
(30),
(31),
(31),
(30),
(31),
(30),
(31);
select *
from @NumDaysMonth;
- >
(12 row(s) affected)
month_id num_days
-------- --------
1 31
2 28
3 31
4 30
5 31
6 30
7 31
8 31
9 30
10 31
11 30
12 31
(12 row(s) affected)
identity
может быть посеян с другим стартовым номером или приращением, если требуется.
Ответ 5
Может использовать UDF вместо этого и настраивать его на любой год.
-- =============================================
-- Author: Alexander Melnichuk for StackOverflow.com
-- Create date: 2013-03-12
-- Description: Number of days in a month
-- =============================================
CREATE FUNCTION [dbo].[f_NumDaysMonth] (
@Year datetime = NULL -- Month and day are ignored. Null gets current year.
)
RETURNS
@Ret TABLE (
month_id smallint,
num_days smallint
)
AS
BEGIN
SET @Year = convert(datetime, convert(varchar(4),
isnull(@Year, getdate()), 112) + '0101', 112)
WITH
seq AS
(--==== Returns table of values from 1 to 12
SELECT TOP (12)
N = ROW_NUMBER() OVER (ORDER BY t1.Object_ID)
FROM Master.sys.All_Columns t1 -- There are certainly more than 12 columns in your Master database ;)
--CROSS JOIN Master.sys.All_Columns t2 -- Uncomment if you need more values. Not this time though.
)
INSERT INTO @Ret
SELECT N,
day(dateadd(day, -1, dateadd(month, N, @Year)))
FROM seq
RETURN
END
Использование:
SELECT * FROM [dbo].[f_NumDaysMonth] ('20130101')
Время выполнения - 0 мс.:)