#sql #sql-server #sql-server-2008
#sql #sql-сервер #sql-server-2008
Вопрос:
У меня есть таблица, в которой будут храниться даты текущего года, у меня также есть дата начала в этой таблице. Есть ли какая-либо возможность получить все даты между текущей и начальной датой с помощью ПЕРЕКРЕСТНОГО ПРИМЕНЕНИЯ.
Ex:
Current_Year Start_Date
2014-06-12 2011-01-01
2014-04-12 2011-01-01
2014-02-12 2011-01-01
2014-01-12 2011-01-01
I want result set like
Year
2014-06-12 2011-01-01
2014-04-12 2011-01-01
2014-02-12 2011-01-01
2014-01-12 2011-01-01
2013-06-12 2011-01-01
2013-04-12 2011-01-01
2013-02-12 2011-01-01
2013-01-12 2011-01-01
2012-06-12 2011-01-01
2012-04-12 2011-01-01
2012-02-12 2011-01-01
2012-01-12 2011-01-01
2011-06-12 2011-01-01
2011-04-12 2011-01-01
2011-02-12 2011-01-01
2011-01-12 2011-01-01
Комментарии:
1. и как это
cross apply
выглядит?2. Но почему так важно, чтобы вы использовали ПЕРЕКРЕСТНОЕ ПРИМЕНЕНИЕ? этот результат может быть достигнут и другими способами.
Ответ №1:
Следующее даст желаемые результаты с использованием ПЕРЕКРЕСТНОГО ПРИМЕНЕНИЯ:
WITH T AS
( SELECT Current_Year = CAST(cy AS DATE), Start_Date = CAST(sd AS DATE)
FROM (VALUES
('2014-06-12', '2011-01-01'),
('2014-04-12', '2011-01-01'),
('2014-02-12', '2011-01-01'),
('2014-01-12', '2011-01-01')
) t (cy, sd)
)
SELECT Current_Year = DATEADD(YEAR, - n.Number, t.Current_Year),
t.Start_Date
FROM T
CROSS APPLY
( SELECT TOP 1000 ROW_NUMBER() OVER (ORDER BY a.object_id) - 1
FROM sys.all_objects AS a
) AS n (Number)
WHERE DATEADD(YEAR, - n.Number, t.Current_Year) > t.Start_Date;
Но ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ будет работать одинаково хорошо и, возможно, будет иметь больше смысла семантически, хотя план выполнения в конечном итоге останется тем же.
Комментарии:
1. это довольно легко сделать с помощью cte и #temp, но из-за требований моего проекта, который содержит объемные данные, не может этого сделать, я попробовал #temp и cte, но время выполнения слишком велико. Поэтому мне нужен какой-то механизм, который может сделать это с перекрестным применением.
Ответ №2:
DECLARE @TAB1 TABLE (CURRENT_YEAR DATE)
INSERT INTO @TAB1 VALUES('2014-06-12'),('2014-04-12'),('2014-02-12'),('2014-01-12')
DECLARE @TAB2 TABLE (CURRENT_YEAR DATE)
INSERT INTO @TAB2 VALUES('2011-01-01'),('2011-01-01'),('2011-01-01'),('2011-01-01')
SQL:
SELECT DATEADD(YY,
LU.[ROW] * (-1),A.CURRENT_YEAR) [YEAR],LU.CURRENT_YEAR [Static_YEAR]
FROM @TAB1 A,
(SELECT *,(ROW_NUMBER() OVER (ORDER BY CURRENT_YEAR)) - 1 [ROW] FROM @TAB2) LU
Результат
Ответ №3:
Это должно сработать в вашем случае:
SELECT *
FROM (SELECT Current_Year
FROM TableName) AS Current_Year
, (SELECT Start_Date
FROM TableName) AS Start_Date
Перекрестное применение используется, когда у вас есть функция, которая возвращает скалярное значение в правой части вашего соединения.