【问题标题】:Is this code achieving what I want?这段代码是否实现了我想要的?
【发布时间】:2016-03-14 23:07:45
【问题描述】:

我正在尝试创建一个查询,用于评估特定车辆的所有者在某个时间点的身份。车辆的目击记录包含在vehicle_sightings 表中。这个查询有点棘手的是,vehicle_vrn 和 vehicle_ownership 表是历史的。所以我需要做的是在瞄准点获取车辆的 VRN 和所有者(基于 vehicle_sightings 表中的seenDate 字段。

SELECT 
    sighting_id
FROM
    vehicle_sightings
        INNER JOIN
    vehicle_vrn ON vehicle_sightings.plate = vehicle_vrn.vrnno
        INNER JOIN
    vehicle_ownership ON vehicle_vrn.fk_sysno = vehicle_ownership.fk_sysno
WHERE
    vehicle_sightings.seenDate >= vehicle_ownership.ownership_start_date
        AND (vehicle_sightings.seenDate <= vehicle_ownership.ownership_end_date
        OR vehicle_ownership.ownership_end_date IS NULL
        OR vehicle_ownership.ownership_end_date = '0001-01-01 00:00:00')
GROUP BY sighting_id
    HAVING seenDate >= MAX(ownership_start_date);  

我已经尝试了上述查询的许多变体,但除了上面粘贴的那个之外,它们似乎都没有得到想要的结果。然而,我担心的是它并没有像我想要的那样工作,因为我对GROUP BY 语句没有太多经验。

因此,我想要的是,在像下面的屏幕截图这样的情况下,使用ownership_start_date 最接近seenDate 的记录,而忽略其他记录。此外,在指定了 end_date 的情况下,这些都无关紧要。此场景仅在未指定 end_date 且历史条目超过 1 个的情况下出现。

我在正确的轨道上吗?这个查询有意义吗?它是否也考虑了vehicle_vrn 历史数据,因为也可能存在相同vrn 有多个条目但vrn_start_dates 不同的情况。

【问题讨论】:

  • 对不起我的英语。但目击意味着was seen?你能用架构准备一个sqlfiddle.com吗?
  • 我尝试阅读您的问题的其余部分,但我不清楚您想要什么。您需要包含更大的样本数据,并根据该数据解释期望的结果。还需要包含您的数据库架构。请阅读How-to-Ask 这里是START 了解如何提高问题质量并获得更好答案的好地方。

标签: mysql sql database


【解决方案1】:

你快到了。但是,您的 HAVING 子句不会有任何效果(每个组中最新的 ownership_start_date 必须在 seenDate 之前,因为您已明确要求 WHERE 子句中的每个组成记录都必须这样做)。

您所追求的是group-wise maximum,它可以通过将您的分组结果连接回基础表来获得。例如:

SELECT * FROM vehicle_ownership JOIN (
  SELECT
      vehicle_sightings.*,
      vehicle_ownership.fk_sysno,
      MAX(vehicle_ownership.ownership_start_date) AS ownership_start_date
  FROM
      vehicle_sightings
          INNER JOIN
      vehicle_vrn ON vehicle_sightings.plate = vehicle_vrn.vrnno
          INNER JOIN
      vehicle_ownership ON vehicle_vrn.fk_sysno = vehicle_ownership.fk_sysno
  WHERE
      vehicle_sightings.seenDate >= vehicle_ownership.ownership_start_date
          AND (vehicle_sightings.seenDate <= vehicle_ownership.ownership_end_date
          OR vehicle_ownership.ownership_end_date IS NULL
          OR vehicle_ownership.ownership_end_date = '0001-01-01 00:00:00')
  GROUP BY sighting_id
) t USING (fk_sysno, ownership_start_date)

【讨论】:

  • 感谢您的建议。实际上,我以前从未见过“使用”语句 - 它是否有助于实现我所追求的目标?
  • @DotNET: a JOIN b USING (col) 本质上只是a JOIN b ON a.col = b.col 的简写(除了col 没有表限定符不会在结果中产生歧义)。正如我在回答中所解释的那样,帮助您实现目标的是将分组结果连接回vehicle_ownership 表。
  • 太好了,我试试看!它是否也满足vehicle_vrn 历史值?由于除了取最接近seenDate的vehicle_start_date外,还需要取vrn_start_date最接近seenDate的vrn500值
  • @DotNET:不,我没有考虑到这一点。如果没有一些示例数据,我很难准确地描述正在发生的事情......虽然我想你需要根据日期进一步限制vehicle_vrn上的加入,就像你对@987654332所做的那样@.
  • 你能解释一下为什么 fk_sysno 和 owner_start_date 都用在 USING 中吗? fk_sysno 是整数列,ownership_start_date 是日期列
猜你喜欢
  • 2013-04-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-27
相关资源
最近更新 更多