我有以下表格格式;
tripID
departureDate (date)
availableJan (bit)
availableFeb (bit)
availableMar (bit)
availableApr (bit)
availableMay (bit)
availableJun (bit)
availableJul (bit)
availableAug (bit)
availableSep (bit)
availableOct (bit)
availableNov (bit)
availableDec (bit)
旅行将 选择任何可用的'标志或出发日期。
我想要做的是一个数据库功能,它会根据当前日期将标志转换为可用日期。
因此,如果旅行的出发日期为空,并且在8月,9月,10月可用,则当前日期为2016年5月8日。我希望功能返回2016年8月1日。
此处的逻辑是该函数返回当前日期下一个可用月份的第一天。
更多例子,例如今天是06/06/2016;
月旗为真:1月,2月,3月 预计产量:2017年1月1日
月旗为真:Jan,Jun
预期产出:2016年6月1日
月旗为真:6月,7月,8月,12月 预期产出:2016年6月1日
我已经绕过圈子尝试大的if语句,临时表但我想知道是否有更聪明的方法来实现这个并不会杀死处理器。
任何帮助非常感谢,
谢谢,
尼克
答案 0 :(得分:0)
从今天开始的第一个月开始
with start as (
select dt = dateadd(YEAR,datediff(YEAR,'20000101',getdate()),'20000101')
)
select tripID
, firstDate = (
select min(d)
from (
select d = start.dt where availableJan = 1
union all
select d = dateadd(MONTH,1,start.dt) where availableFeb = 1
union all
select d = dateadd(MONTH,2,start.dt) where availableMar = 1
-- ...
)
where d >= getdate() )
from mytable
join start;
答案 1 :(得分:0)
根据Serg的回答(谢谢!),我设法通过以下方式获得了预期的结果;
DECLARE @firstDayOfCurrentYear date = dateadd(YEAR,datediff(YEAR,'20000101',getdate()),'20000101')
DECLARE @firstOfCurrenyMonth date = CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(GETDATE())-1),GETDATE()),101)
SELECT
itinerary.*,
COALESCE
(
departureDate,
(
SELECT MIN(d) FROM
(
SELECT @firstDayOfCurrentYear AS d WHERE availableJan = 1 UNION ALL
SELECT DATEADD(MONTH,1,@firstDayOfCurrentYear) AS d WHERE availableFeb = 1 UNION ALL
SELECT DATEADD(MONTH,2,@firstDayOfCurrentYear) AS d WHERE availableMar = 1 UNION ALL
SELECT DATEADD(MONTH,3,@firstDayOfCurrentYear) AS d WHERE availableApr = 1 UNION ALL
SELECT DATEADD(MONTH,4,@firstDayOfCurrentYear) AS d WHERE availableMay = 1 UNION ALL
SELECT DATEADD(MONTH,5,@firstDayOfCurrentYear) AS d WHERE availableJun = 1 UNION ALL
SELECT DATEADD(MONTH,6,@firstDayOfCurrentYear) AS d WHERE availableJul = 1 UNION ALL
SELECT DATEADD(MONTH,7,@firstDayOfCurrentYear) AS d WHERE availableAug = 1 UNION ALL
SELECT DATEADD(MONTH,8,@firstDayOfCurrentYear) AS d WHERE availableSep = 1 UNION ALL
SELECT DATEADD(MONTH,9,@firstDayOfCurrentYear) AS d WHERE availableOct = 1 UNION ALL
SELECT DATEADD(MONTH,10,@firstDayOfCurrentYear) AS d WHERE availableNov = 1 UNION ALL
SELECT DATEADD(MONTH,11,@firstDayOfCurrentYear) AS d WHERE availableDec = 1 UNION ALL
SELECT DATEADD(MONTH,12,@firstDayOfCurrentYear) AS d WHERE availableJan = 1 UNION ALL
SELECT DATEADD(MONTH,13,@firstDayOfCurrentYear) AS d WHERE availableFeb = 1 UNION ALL
SELECT DATEADD(MONTH,14,@firstDayOfCurrentYear) AS d WHERE availableMar = 1 UNION ALL
SELECT DATEADD(MONTH,15,@firstDayOfCurrentYear) AS d WHERE availableApr = 1 UNION ALL
SELECT DATEADD(MONTH,16,@firstDayOfCurrentYear) AS d WHERE availableMay = 1 UNION ALL
SELECT DATEADD(MONTH,17,@firstDayOfCurrentYear) AS d WHERE availableJun = 1 UNION ALL
SELECT DATEADD(MONTH,18,@firstDayOfCurrentYear) AS d WHERE availableJul = 1 UNION ALL
SELECT DATEADD(MONTH,19,@firstDayOfCurrentYear) AS d WHERE availableAug = 1 UNION ALL
SELECT DATEADD(MONTH,20,@firstDayOfCurrentYear) AS d WHERE availableSep = 1 UNION ALL
SELECT DATEADD(MONTH,21,@firstDayOfCurrentYear) AS d WHERE availableOct = 1 UNION ALL
SELECT DATEADD(MONTH,22,@firstDayOfCurrentYear) AS d WHERE availableNov = 1 UNION ALL
SELECT DATEADD(MONTH,23,@firstDayOfCurrentYear) AS d WHERE availableDec = 1
) AS dateTable where d >= @firstOfCurrenyMonth
)
) AS inclusiveDepartureDate
FROM
itinerary
这个帐户指的是月份是一年中的一部分,所以下一个出发日期是在下一年(即我联合24行,而不仅仅是12行)。
我使用COALESCE只在正常的departureDate为空时才执行此操作。
答案 2 :(得分:0)
每当你想到写一堆像那样的UNION语句时,想想 fold 。您想要的是旅行的最短可用日期。因此,首先制作日期,然后将它们放在一列中,然后选择最小的一个。整个shebang可以是一对一select
声明。
首先,让自己成为一个包含整数1-12的12行静态表。我们称之为Months
。然后
with start as (
select dt = dateadd( YEAR,
datediff(YEAR, '20000101', getdate()),
'20000101' )
)
select TripId, min(departure) as Departure
select TripID
, case month
when 1 then case availableJan
when 1 then dateadd(MONTH,month,start.dt) end
when 2 then case availableFeb
when 1 then dateadd(MONTH,month,start.dt) end
--- 10 more times --
end as departure
from itinerary cross join Months
) as M
where departure >= getdate()
group by TripID
此技术称为 folding ,可能被认为与 pivoting 相反(即将行排列为列)。 DBMS执行通常比一系列UNIONS更有效,因为 - 即使有很多SQL - 只有一个提到表。通过对数据进行单次传递可以产生结果;服务器唯一的问题是如何处理每一行。它也不那么罗嗦了,一旦你习惯了它,一个容易识别的习语。