用于计算表中的正确提前期的SQL查询(MS Access)

时间:2009-03-12 15:09:40

标签: sql ms-access

我有下表:log(productId, status, statusDate, department...),其中productId,status和statusDate是主键。 例如:

id1 01 01/01/2009
id1 02 02/01/2009
id1 03 03/01/2009
id1 01 06/01/2009
id1 02 07/01/2009
id1 03 09/01/2009
id2 01 02/01/2009
id2 02 03/01/2009
id2 01 04/01/2009
id2 03 06/01/2009
id3 01 03/01/2009
id3 02 04/01/2009

我想创建一个查询,检索status03中的每个productId,它是第一次到达status01和status03之间经过的时间。预期结果:

id1 2
id1 3
id2 4

任何的想法?谢谢

3 个答案:

答案 0 :(得分:2)

怎么样:

SELECT t.ID, t.Status, t.SDateTime, 
    (SELECT Top 1 SDateTime 
     FROM t t1 WHERE t1.Status = 1 
     AND t1.ID=t.ID 
     AND t1.SDateTime<t.SDateTime 
     AND t1.SDateTime>=
         Nz((SELECT Top 1 SDateTime 
             FROM t t2 
             WHERE t2.Status=3 
             AND t2.ID=t.ID 
             AND t2.SDateTime<t.SDateTime),0)) AS DateStart, 
[SDateTime]-[DateStart] AS Result
FROM t
WHERE t.Status=3

答案 1 :(得分:1)

我喜欢这样的东西。看起来它比迄今为止建议的其他两个答案中的任何一个都要复杂。这是一个有效的解决方案。我为讨厌的格式道歉。此外,这将在SQL Server中工作,但我没有永久使用Access,因此您可能需要稍微调整一下才能在那里工作。或者,如果Access不支持非等值连接,它可能根本不起作用。

SELECT productId, MAX(tbl.TimeBetween)
FROM
 (SELECT status_1.productId as productId, status_1.statusDate as status1Date, MIN(status_3.statusDate) as status3Date, DATEDIFF(m,status_1.statusDate, MIN(status_3.statusDate)) as TimeBetween
  FROM 
  (SELECT productId, status, statusDate
    FROM log
    WHERE status = '01') status_1
  INNER JOIN
  (SELECT productId, status, statusDate
   FROM log
   WHERE status = '03') status_3
  ON status_1.productId = status_3.productId AND status_3.statusDate > status_1.statusDate
  GROUP BY status_1.productId, status_1.statusDate) tbl
GROUP BY productId, status3Date
ORDER BY productId, TimeBetween
  1. 最里面的选择获取每个状态的记录。
  2. 然后加入那些以提供大于相应'01'记录的'03'状态记录(你多久使用一次非等值的?)
  3. 然后对它们进行过滤,以得到仍然在相应的'01'记录之后的MIN'03'记录。
  4. 最外面的选择会强制执行您的'第一次达到'01'状态规则',因为它可能会在达到'03'状态之前多次进入'01'状态。
  5. 如果其他人有更优雅的解决方案,我很乐意看到它。我过去不得不写这样的问题,我很想看到更好的解决这类问题的方法。

答案 2 :(得分:-3)

这可以在Sql Server中使用。您可能需要为Access部分翻译部分内容:

SELECT l3.productID, DATEDIFF(d,COALESCE(l1.statusDate,l3.statusDate),l3.statusDate) AS LeadTime
FROM log l3
LEFT JOIN log l1 ON l1.productID=l3.productID AND l1.Status='01'
    AND l1.statusDate = 
      (
         SELECT TOP 1 statusDate 
         FROM log lsub 
         WHERE lsub.Status='01' AND lsub.productID=l1.productID AND l1.statusDate<l3.StatusDate
         ORDER BY statusDate DESC
      )
WHERE l3.Status='03'