【问题标题】:sql join by datessql 按日期连接
【发布时间】:2017-03-26 14:48:57
【问题描述】:

我目前正在使用 SQL Server 2016...

在编写新查询时需要帮助 -

我有两张桌子——销售和员工。

销售可能如下所示:

Employees 表可能如下所示:

我想调用sales表中的所有行并从employees表中引入supervisor字段-但是,我需要根据employee表中的date_to和date_from字段加入supervisor字段。例如,我希望我的输出如下所示:

主管和销售代表的一致性取决于销售表中的日期以及该日期在员工表中的 date_from 和 date_to 字段之间的位置。在这种情况下,由于 11/4 的第一次销售是在 2016 年 1 月 1 日到 2016 年 11 月 6 日之间 - 当我们加入员工表中的 sales_rep_id 时,主管将是 Jim Jones。但是,2016 年 11 月 15 日发生的销售介于 2016 年 11 月 7 日和 2999 年 12 月 31 日之间,这与 Tom Hall 是主管有关。

感谢任何帮助!

【问题讨论】:

  • 您的代码中缺少逗号。
  • 指定您正在使用的 DBMS
  • @EmilHolub SQL Server 2016
  • 在以后的参考中,代替图片,给我们表格的文本格式。您可以在 SSMS 中使用快捷键 CTRL+T 执行此操作。它加快了这个过程。哦,选择解决您问题的答案。 ;)

标签: sql sql-server tsql date join


【解决方案1】:

设置:

create table Sales
(
    sale_date DATE,
    sales_rep_name NVARCHAR(100),
    sales_rep_id INT,
)
GO

insert into Sales VALUES 
    ('20161004', 'Old man', 123),
    ('20161104', 'Smith, John', 12345), 
    ('20161115', 'Smith, John', 12345)
GO

create table Employees 
(
    sales_rep_name NVARCHAR(100),
    sales_rep_id INT,
    supervisor NVARCHAR(100),
    date_from DATE,
    date_to DATE
)
GO

测试:

INSERT INTO Employees VALUES ('Smith, John', 12345, 'Jones, Jim', '20160101', '20160611'),
    ('Smith, John', 12345, 'Hall, Tom', '20160711', '99991231')
GO

-- gets all sales where INNER JOIN will go
-- even if LEFT JOIN is used, BETWEEN applied to NULL will rule out some records
SELECT S.sale_date, E.sales_rep_name, S.sales_rep_name, E.supervisor 
FROM Sales S
    JOIN Employees E ON S.sales_rep_id = E.sales_rep_id
         AND S.sale_date BETWEEN E.date_from and E.date_to


联合所有

-- just NULL the columns for the rest of the records
SELECT S.sale_date, NULL, S.sales_rep_name, NULL
FROM Sales S
    WHERE NOT EXISTS (SELECT 1 FROM Employees E WHERE E.sales_rep_id = S.sales_rep_id AND S.sale_date BETWEEN E.date_from and E.date_to)

去吧

【讨论】:

  • 只需将WHERE S.sale_date BETWEEN 更改为AND S.sale_date BETWEEN,就不需要UNION:)
【解决方案2】:

您的员工表是所谓的Slowly Changing Dimension Type 2,您需要 BETWEEN 作为外部联接的附加条件:

SELECT *
FROM SALES AS sal
LEFT JOIN EMPLOYEES AS emp
  ON sal.SALES_REP_ID = emp.SALES_REP_ID
 AND sal.DATE BETWEEN emp.DATE_FROM AND emp.DATE_TO 

不要将 BETWEEN 放在 WHERE 中,因为这会将结果再次变成 Inner Join。

【讨论】:

    【解决方案3】:

    我建议您使用LEFT JOIN,这样您就不会错过任何销售。以下是正确的使用方法:

    SELECT s.Date, e.sales_rep_name, s.sales_rep_id, e.supervisor
    FROM sales s LEFT JOIN
         employees e
         ON s.sales_rep_id = e.sales_rep_id AND
            s.date >= e.date_from AND
            s.date <= e.date_to;
    

    请注意,日期条件需要放在ON 子句中,用于LEFT JOIN。此外,表别名使查询的编写和读取更容易。如果 sales 没有匹配项,则来自sales 的信息将在结果集中,NULL 值来自employees 的列。

    【讨论】:

      猜你喜欢
      • 2015-08-02
      • 2023-01-29
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      • 2020-01-04
      • 1970-01-01
      • 1970-01-01
      • 2021-12-06
      相关资源
      最近更新 更多