MSSQL-获取另一列的最大日期分组的主键

时间:2018-10-30 14:11:33

标签: sql sql-server tsql

在不使用SQL Windows函数,CLR或CTE的情况下,我该怎么做?

考虑此数据集:

Dispatch_Id (PK)    | Job_Id    | Tech  | Scheduled_Time
    1               |   1       | Brad  |   08:35
    2               |   1       | John  |   05:29
    3               |   2       | Steve |   13:02
    4               |   3       | Brad  |   10:15
    5               |   3       | Kevin |   10:15
    6               |   4       | Kevin |   12:00

这就是我要结束的:

Dispatch_Id (PK)    | Job_Id    | Tech  | Scheduled_Time
    2               |   1       | John  |   05:29
    3               |   2       | Steve |   13:02
    4               |   3       | Brad  |   10:15
    6               |   4       | Kevin |   12:00

这是我已经开始的代码,但问题是它没有获得MIN(Scheduled_Time)的MIN(Dispatch_Id)。我需要他们一起努力。

SELECT   Job.Name
        ,NextAppt.Next_Appointment
        ,Tech.Tech_Name
FROM Job
 LEFT JOIN (SELECT Job_Id, MIN(Schedule_Time) AS Next_Appointment, MIN(Dispatch_Id) AS Dispatch_Id
            FROM Dispatch
            GROUP BY Job_Id) NextAppt ON Job.Job_Id = NextAppt.Job_Id
  LEFT JOIN Dispatch ON NextAppt.Dispatch_Id = Dispatch.Dispatch_Id
   LEFT JOIN Tech ON Dispatch.Tech_Id = Tech.Tech_Id

感谢您的帮助。

编辑:

这是我过去所做的事情,但它使我头疼,并且在进行大型查询时很慢。加上这会对调度ID进行字母数字排序。因此,当有两个相同的日期时,就不那么精确了。

SELECT   Job.Name
        ,CAST(SUBSTRING(NextAppt.Next_Appointment,1,22) AS DATETIME) AS 'Next_Appointment'
        ,Tech.Tech_Name
FROM Job
 LEFT JOIN (SELECT Job_Id, MIN(CONVERT(NVARCHAR(25),Schedule_Time,126)+'-'+CAST(Dispatch_Id AS NVARCHAR)) AS Next_Appointment
            FROM Dispatch
            GROUP BY Job_Id) NextAppt ON Job.Job_Id = NextAppt.Job_Id
  LEFT JOIN Dispatch ON CAST(SUBSTRING(NextAppt.Next_Appointment,21,99) AS INT) = Dispatch.Dispatch_Id
   LEFT JOIN Tech ON Dispatch.Tech_Id = Tech.Tech_Id

3 个答案:

答案 0 :(得分:1)

您处于正确的轨道,但是您的派生表需要使用TOP 1和ORDER BY而不是MIN。它还需要在Job_Id上进行关联,但要在PK上进行加入。

示例(我知道我之前已经发布了此内容,但我找不到它很容易):

伪代码,因为您仅发布了查询结果而未发布DDL:

SELECT...
FROM SomeTables t1
INNER JOIN Dispatch t2 ON t2.PK=(
  SELECT TOP 1 PK
  FROM Dispatch t3
  WHERE t1.Job_id=t3.Job_id
  ORDER BY Schedule_Time, Dispatch_Id ASC
)

结果t2将具有Job_Id中每个t1的第一个调度行。

答案 1 :(得分:1)

这是我一直在寻找的方法。假设您要加入PK索引,它会进行非常优化。

SELECT   Job.Name
        ,NextAppt.Next_Appointment
        ,Tech.Tech_Name
FROM Job
 OUTER APPLY (SELECT TOP 1 Job_Id, Dispatch_Id, Tech_Id, Schedule_Time AS 'Next_Appointment'
              FROM OE_Job_Dispatch
              WHERE Job_Id = Job.Job_Id
              ORDER BY Scheduled_Time) NextAppt
  LEFT JOIN Tech ON NextAppt.Tech_Id = Tech.Tech_Id

此方法似乎在LEFT JOIN方法中使用了“表查找”与较慢的“表扫描”。这是OUTER APPLY方法:

enter image description here

这是LEFT JOIN方法:

enter image description here

这是我以前的串联JOIN方法: 请记住,如果数据不正确,这可能是不可预测的。在这种情况下,它执行得很好,但是可能不可靠。

enter image description here

答案 2 :(得分:0)

您可以将ROW_NUMBER()TIES子句一起使用:

SELECT TOP (1) WITH TIES d.*
FROM dataset d
ORDER BY ROW_NUMBER() OVER (PARTITION BY Job_Id ORDER BY Scheduled_Time, Dispatch_Id);