ON ON条件中的子选择范围? (为什么和行为有益?)

时间:2016-08-03 09:44:11

标签: sql sql-server tsql

有问题的陈述工作正常,我只需要了解原因和方法!

我在一个语句中遇到了以下语法,该语句获取员工分析的信息。

从未见过类似的东西,也无法找到任何关于使用谷歌的行为。希望你们能帮助我了解它是如何工作的以及如何使用它。

表1员工(员工ID,姓名,出生日期......)

表2合同(ContractID,EmployeeID,Startdate,Enddate,...)

表3时间模型(TimeID,ContractID,EmployeeID,MonthlyDate,......)

表4保险(InsuranceID,ContractID,EmployeeID,JobType,......)

稍后在代码中的子选择输出:

Columname MonthlyDate 
Values('2016-02-01 00:00:00.000',
'2016-04-01 00:00:00.000',
'2016-01-01 00:00:00.000',
'2016-03-01 00:00:00.000',
'2016-06-01 00:00:00.000',
'2016-05-01 00:00:00.000',
'2016-07-01 00:00:00.000')

有问题的SQL如下所示:

SELECT E.EmployeeID+C.ContractID, D.Date, E.Name

FROM Employees AS E

LEFT OUTER JOIN Contract AS C ON E.EmployeeID = C.Employee ID

--This is where the SQL I was talking about starts
LEFT OUTER JOIN (
    SELECT MonthlyDate
    FROM Time-models
    WHERE MonthlyDate >= Convert(DATETIME, '2016-01-01', 102)) AS D 
ON (D.MonthlyDate >= C.ContractStartDate AND D.MonthlyDate <= C.ContractEndDate) 
/*I can not explain this On-Condition*/

LEFT OUTER JOIN Insurance as I 
ON (I.EmployeeID = E.EmployeeID AND I.ContractID = C.ContractID)

WHERE I.JobType = 'Clerk' 
AND (I.InsuranceStartDate <= D.MonthlyDate AND I.InsuranceEndDate >= D.MonthlyDate)
/* I can not understand which compare values are used in D.MonthlyDate 
because of the the vague ON-Condition */

2 个答案:

答案 0 :(得分:1)

您的查询的WHERE条件是将LEFT JOIN变为INNER JOIN。 (如果某行不匹配,则I列将为NULL并且WHERE条件失败。)

另外:

  • 您根本不需要子查询。
  • SQL Server以YYYYMMDD格式识别日期,并且几乎总是以YYYY-MM-DD格式识别,而不进行转换。

因此,您可以将查询重写为:

SELECT E.EmployeeID+C.ContractID, D.Date, E.Name
FROM Employees E JOIN
     Contract C
     ON E.EmployeeID = C.Employee ID JOI
     [Time-models] d
     ON D.MonthlyDate >= C.ContractStartDate AND
        D.MonthlyDate <= C.ContractEndDate AND
        MonthlyDate >= '2016-01-01' JOIN
     Insurance as I 
     ON I.EmployeeID = E.EmployeeID AND
        I.ContractID = C.ContractID
WHERE I.JobType = 'Clerk' AND
      I.InsuranceStartDate <= D.MonthlyDate AND
      I.InsuranceEndDate >= D.MonthlyDate;

我不确定这是否能回答你的问题。

答案 1 :(得分:0)

“我不明白如何匹配单个值。” 不,这显然会匹配多个行,而不是一个行。考虑这个简单的例子

(void)

对于每select * from ( values (1, cast('2016-02-02' as date), cast('2016-03-02' as date)) ,(2, cast('2016-02-02' as date), cast('2016-05-02' as date)) ,(3, cast('2016-02-02' as date), cast('2016-02-04' as date)) ) C(id,ContractStartDate, ContractEndDate) left join ( values ('2016-02-01') ,('2016-04-01') ,('2016-01-01') ,('2016-03-01') ,('2016-06-01') ,('2016-05-01') ,('2016-07-01') ) D(MonthlyDate) on D.MonthlyDate >= C.ContractStartDate AND D.MonthlyDate <= C.ContractEndDate ; 行,查询将从D返回1到3行。