【问题标题】:Need to match two SQL tables based on dates but I need to check for date+1需要根据日期匹配两个 SQL 表,但我需要检查 date+1
【发布时间】:2014-03-28 17:24:32
【问题描述】:

我对 SQL 还很陌生(大约 9 个月左右),所以我很难用 SQL Server 2012 来解决这个问题。

我正在尝试匹配两个如下所示的表格:

Shift:

    Date       |    Name    | Shift
    01-01-2013 | Dan Smith  | Night
    01-02-2013 |John Johnson| Night
    01-03-2013 |John Johnson| Night

Sales

    Date       |    Name    | Sales
    01-01-2013 | Dan Smith  | 3
    01-02-2013 | Dan Smith  | 5
    01-02-2013 |John Johnson| 4
    01-03-2013 |John Johnson| 7
    01-04-2013 |John Johnson| 2

问题是轮班表只包含轮班的开始日期,这对于夜班来说是个问题,因为它需要两天时间。夜班销售显示为在两天内发生,因为它们在发生时带有时间戳。这意味着,如果我只是尝试根据姓名和班次日期链接表格,而该人第二天没有班次,我将错过从上午 12:00 开始的任何销售数据。我正在寻找一种方法来检查该人第二天是否有班次,如果没有,则将他们第二天的销售数据添加到前几天的销售额中。

现在我的代码如下所示:

Select
   st.Name,
   st.Date,
   st.Shift,
   sl.Sales
From 
   Shift st
right join 
   Sales as sl on sl.Name = st.Name
               and sl.Date = Case
                               When sl.Date = DATEADD(DD, 1, st.Date)
                               Then DATEADD(DD,1, st.Date)
                               Else st.Date
                             End

当我简单地使用 sales.date=shift.date 时,它​​会拾取丢失的数据,但最终也会产生大量重复数据。抱歉,如果这很简单,但我还没有找到一种好方法来简单地检查销售人员第二天是否没有轮班,然后将该人的第二天销售数据添加到他们前几天的销售数据中。

编辑:期望的结果看起来像这样:

ShiftDate  |    Name    | Shift | Sales
01-01-2013 | Dan Smith  | Night | 8
01-02-2013 |John Johnson| Night | 4
01-03-2013 |John Johnson| Night | 9

我真的不介意每班的准确销售数字是否不是 100% 准确,但如果他们第二天没有班次,我确实需要获取第二天的销售数据。

我很想改变模型,因为它绝对可以解决这个问题,并且已经努力获得一个一段时间了。不幸的是,销售数据来自外部来源,然后我将其导入我们的数据库,到目前为止,他们一直不愿意/无法提供精确的时间戳。

【问题讨论】:

  • Yakshemash !你不再是新人了。我只做 3 个月的 SQL :) 你的数据库需要包含所有时间戳。
  • 你能发布想要的结果吗?
  • 我们怎么知道如何将 John Johnson 的销售额分配给 01-03-2013?,您将其显示给 01-03-2013 班次,但也可以是您自己的 01-02-2013规则
  • 你不能,这就是为什么我希望找到一种方法来简单地根据销售日进行汇总,除非它是该人连续的最后一个班次,在这种情况下它将它添加到前一天。

标签: sql sql-server date


【解决方案1】:

好的,这如你所愿:

;WITH Sales2 AS
(
    SELECT A.*, CASE WHEN B.[Date] IS NULL THEN 1 ELSE 0 END LastShift
    FROM Sales A
    LEFT JOIN Sales B
      ON A.Name = B.Name
      AND A.[Date] = DATEADD(DAY,-1,B.[Date])
)
SELECT  A.[Date],
        A.Name,
        A.Shift,
        SUM(B.Sales) Sales
FROM Shift A
LEFT JOIN Sales2 B
  ON A.Name = B.Name
  AND CASE 
        WHEN A.Shift <> 'Night' AND A.[Date] = B.[Date] 
            THEN 1
        WHEN A.Shift = 'Night' AND B.LastShift = 0 AND A.[Date] =  B.[Date]
            THEN 1 
        WHEN A.Shift = 'Night' AND B.LastShift = 1 AND A.[Date] = DATEADD(DAY,-1,B.[Date]) 
            THEN 1 
        ELSE 0 
      END = 1
GROUP BY A.[Date],
         A.Name,
         A.Shift

Here is a sqlfiddle 带有此解决方案的演示。

结果是:

╔═════════════════════════╦══════════════╦═══════╦═══════╗
║          Date           ║     Name     ║ Shift ║ Sales ║
╠═════════════════════════╬══════════════╬═══════╬═══════╣
║ 2013-01-01 00:00:00.000 ║ Dan Smith    ║ Night ║     8 ║
║ 2013-01-02 00:00:00.000 ║ John Johnson ║ Night ║     4 ║
║ 2013-01-03 00:00:00.000 ║ John Johnson ║ Night ║     9 ║
╚═════════════════════════╩══════════════╩═══════╩═══════╝

【讨论】:

    【解决方案2】:

    您有模型问题。我建议您定义另一个表来定义实际的开始和结束日期。您将能够使用该表将销售安排在正确的日期和相应的班次。

    【讨论】:

    • 只要!销售数据来自外部来源(不要问),然后我将其导入我们的数据库,他们没有/不愿意/没有能力提供精确的时间戳。这是我几个月来一直试图解决的问题,但可能不会发生。
    【解决方案3】:

    我认为您可能需要更好的模型。看看这是否有效?

    SELECT  
        sft.Name,
        sft.Date,
        sft.Shift,
        sum(sls.Sales)       
    FROM Sales sls  
    LEFT JOIN Shift sft
       ON sls.Date >= sft.Date
    WHERE  (sls.Date = sft.Date OR sls.Date NOT IN   
            (SELECT Date FROM Shift WHERE Date = sls.Date AND Name = sls.Name ))
    GROUP BY 
        sft.Name,
        sft.Date,
        sft.Shift
    

    【讨论】:

    • 列名“销售”无效。无法对包含聚合或子查询的表达式执行聚合函数。
    • @BoratSagdiyev 谢谢我做了一些改变。
    • ON sls.Date >= sft.Sales - 列名“销售”无效。
    • @BoratSagdiyev 再次感谢。
    • 现在有一些输出了。不知道这是否是操作人员想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多