SQL在&x; xxxx-xx-xx'之前获得第一个可用日期

时间:2016-05-16 15:06:12

标签: sql sql-server tsql

我需要一个查询来让第一个可用日期向后移动,不包括不可用日期。
示例:
日期必须在2016-05-19之前(此日期是变量)。最佳选择是SELECT blockedDate FROM tbl_BlockedDates(前一天)。如果没有,那就提前一天 不可用日期保存在表格中,可以像这样选择 SELECT TOP 1 [Date] FROM ( SELECT TOP (DATEDIFF(DAY, @Date1, @Date2)+1) [Date] = dateadd(DAY, ROW_NUMBER() OVER(ORDER BY c1.name), @Date1) FROM [master].[dbo].[spt_values] c1 ) D WHERE D.Date NOT IN (SELECT ClosingDate FROM ClosingDays WHERE IsClosedAllDay = 1) and Date not in (SELECT blockedDate FROM tbl_BlockedDates )

编辑:
我已经看到这样的东西会起作用,但我无法弄清楚如何根据我的情况正确设置

            List fragments = getSupportFragmentManager().getFragments();
            mCurrentFragment = fragments.get(fragments.size() - 1);

如何获得我需要的日期?

6 个答案:

答案 0 :(得分:4)

您需要一个日期表

Declare @start_date datetime = '2014-01-01', 
        @varibale_date datetime = '2016-05-20'

;WITH e1(n) AS
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), -- 10
e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 AS b), -- 10*10
e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2), -- 10*100
e4(n) AS (SELECT 1 FROM e3 CROSS JOIN e2), 
Tally(n) AS (select  ROW_NUMBER() OVER (ORDER BY n) FROM e4),
dates(dt) AS (select DATEADD(dd,n-1,@start_date) from tally)
SELECT TOP 1 dt 
FROM   dates 
WHERE  dt < @varibale_date 
       AND NOT EXISTS (SELECT 1 FROM tbl_blockeddates t 
                       WHERE  t.blockeddate = dt) 
ORDER  BY dt DESC 

答案 1 :(得分:2)

这比听起来更复杂,因为你可能有一系列被阻止的日期,并且必须在前一天获得。

如果没有阻止日期或阻止日期在相关日期之前有间隙,这很简单:

driver.find_element_by_id("header_wallet_balance").text

with bd as ( select bd.*, max(grp) as maxgrp from (select bd.*, dateadd(day, - row_number() over (order by blockeddate), blockeddate) as grp from tbl_BlockedDates bd where blockedDate < @Date ) bd ) select (case when max(blockedDate) is null or max(blockedDate) <> dateadd(day, -1, @Date) then dateadd(day, -1, @Date) else dateadd(day, -1, min(case when grp = maxgrp then blockedDate end)) end) as FreeDate from bd; 部分是棘手的部分。 else定义了一组连续日期。 grp获取此类组的第一个日期并在当天减去。

答案 2 :(得分:2)

DECLARE @DateVariable DATE = '20160520';

SELECT  TOP (1) 
        YT.yourDate 
FROM    yourTable AS [YT] 
WHERE   YT.yourDate < @DateVariable
AND NOT EXISTS (SELECT 1 FROM tbl_BlockedDate AS [bd] WHERE bd.blockedDate = YT.yourDate)
ORDER BY 
    YT.yourDate DESC;

这里的一个问题是,您还没有向我们提供您的日历表的DDL语句(如果您没有,那么Zohar Peled会为此提供一个很好的解决方案。您的问题的评论)。

但是,如果您确实有一个日历表或包含日期的表,您可能需要警惕其中的多个条目与tbl_BlockedDate表中不存在的日期相同。

示例

ID  |  Date         |
---------------------
1   | '2016-05-20'  |
2   | '2016-05-19'  |
3   | '2016-05-19'  |
4   | '2016-05-19'  |
5   | '2016-05-19'  |

上述查询将返回1行,日期为19,但多行符合查询。

如果您将查询更改为包含WITH TIES,它将返回所有包含第19条的4条记录,因为它们都满足此查询。

SELECT  TOP (1) WITH TIES
        YT.yourDate 
FROM    yourTable AS [YT] 
WHERE   YT.yourDate < @DateVariable
AND NOT EXISTS (SELECT 1 FROM tbl_BlockedDate AS [bd] WHERE bd.blockedDate = YT.yourDate)
ORDER BY 
    YT.yourDate DESC;

这就是为什么建议您在订单中添加另一个标识列,以便希望消除此问题。

以下示例使用组成列ID返回包含Date: '2016-05-19'ID: 2的行。

SELECT  TOP (1) 
            YT.yourDate 
    FROM    yourTable AS [YT] 
    WHERE   YT.yourDate < @DateVariable
    AND NOT EXISTS (SELECT 1 FROM tbl_BlockedDate AS [bd] WHERE bd.blockedDate = YT.yourDate)
    ORDER BY 
        YT.yourDate DESC,
        YT.identifying_column ASC;

答案 3 :(得分:0)

感谢所有花时间回应的人。通过结合所有答案,这对我有用。

DECLARE @date = '2016-05-16'
SELECT TOP 1 [Date]
FROM (
    SELECT TOP 120 
    [Date] = dateadd(DAY, -ROW_NUMBER() OVER(ORDER BY c1.name), @date)
    FROM  [master].[dbo].[spt_values] c1 
) D 
WHERE D.Date  NOT IN (select blockedDate from tbl_BlockedDates)

通过使用否定-ROW_NUMBER(),我创建了一个日期表,从传递的日期开始逐渐减少。我加入了Tbl_blockedDates以从表中排除这些日期。 然后我选择了TOP[1]以获得第一个可用日期。

答案 4 :(得分:0)

你应该能够使用一个简单的递归cte而不需要任何额外的表..

;WITH cte AS (
    SELECT DATEADD(DAY, -1, @StartDate) [Start]
    UNION ALL 
    SELECT DATEADD(DAY, -1, [Start]) 
    FROM   cte
    INNER JOIN @tbl_BlockedDates ON cte.[Start] = blockedDate
)
SELECT MIN([Start]) FROM cte

SQL Fiddle Demo

答案 5 :(得分:0)

CREATE TABLE [dbo].[tbl_BlockedDates](
    [BlockedDate] [date] NOT NULL
) ON [PRIMARY]

INSERT INTO [dbo].[tbl_BlockedDates]([BlockedDate]) VALUES ('2016-05-16');
INSERT INTO [dbo].[tbl_BlockedDates]([BlockedDate]) VALUES ('2016-05-15');
INSERT INTO [dbo].[tbl_BlockedDates]([BlockedDate]) VALUES ('2016-05-14');
INSERT INTO [dbo].[tbl_BlockedDates]([BlockedDate]) VALUES ('2016-05-12');
INSERT INTO [dbo].[tbl_BlockedDates]([BlockedDate]) VALUES ('2016-05-11');

  Declare @MyDate as Date , @CheckDate as date, @BestDate as Date

  Set @MyDate = '2016-05-16';
  Set @CheckDate = '2016-05-16';

  while (@BestDate is null)
  Begin
    Set @CheckDate = DateAdd(day,-1,@CheckDate)
    If  NOT Exists (Select 1 from tbl_BlockedDates where BlockedDate = @CheckDate)
        begin
            Select @BestDate = @CheckDate
        end
    END


    Select @BestDate as BestDate