1

我有两个相关的表,其中包含许多基于日期的记录。我只需要选择基于特定日期的有效汇率。

这些是数据示例:

在 HEADERTABLE 上...

ID, PICKUP, DELIVERY, VALIDFROM, VALIDTO, COMMODITY, CARRIER
1, 纽约, 芝加哥, 01-OCT-13,31-OCT-13, 鞋类, DHL
2、纽约、芝加哥、20-OCT-13、31-OCT-13、鞋类、UPS
3、纽约、芝加哥、30-OCT-13、31-OCT-13、鞋类、DHL
4,纽约,芝加哥,30-OCT-13,31-OCT-13,木制品,DHL

在线表上:

ID、HEADERTABLEID、RATEDESC、RATE
2325, 1, 交付, 1000
2354, 2, 交付, 1500
2355, 2, 税, 100
2355, 3, 交付, 1200
2356, 3, 税务, 110
2380, 4, 交付, 1000

因此,通过使用某个日期(下面的日期变量),我只需要显示一个选项。例如,如果 thedate=25-oct-13,则要显示的记录是 Id 2(来自 headertable + 行表中的链接汇率)

如果 thedate=10-oct-13,那么选项 1 就是要显示的选项。

如果 thedate=30-oct-13,那么将显示 2 条记录(Id 3 和 4)(区别是商品)

这是我正在使用的代码(我已经尝试了很多其他代码,但没有运气)但显然缺少一些东西,因为它显示了所有记录。

任何帮助表示赞赏。

SELECT  * from schema1.headertable, schema1.linestable
WHERE headertable.Id= linestable.headertableId
AND headertable.Validfrom <= STR_TO_DATE('" & thedate & "','%Y-%m-%d')
AND headertable.Validto >= STR_TO_DATE('" & thedate & "','%Y-%m-%d')
AND headertable.PICKUP LIKE '%NEW YORK%'
AND headertable.DELIVERY LIKE '%CHICAGO%'
ORDER BY headertable.Validfrom DESC, linestable.Id DESC
4

3 回答 3

1

好的,让我们以结构化的方式解决这个问题,与我们使用结构化查询语言的想法相一致。

首先,我们需要从您那里获取headertable与您的日期匹配的行。此查询在http://sqlfiddle.com/#!2/dff43/4/0中挑选出匹配的行headertable。其中有两行。

SELECT headertable.*
  FROM ( SELECT STR_TO_DATE('2013-10-25', '%Y-%m-%d') AS thedate) d
  JOIN headertable
 WHERE headertable.Validfrom <= thedate
   AND headertable.Validto   >= thedate
   AND headertable.PICKUP LIKE '%NEW YORK%'
   AND headertable.DELIVERY LIKE '%CHICAGO%'

注意与SELECT STR_TO_DATE(.... 这让我们thedate只需将参数放入查询中一次,并多次使用它。

但是您的规范只需要其中一行,而不是两行。我们必须通过选择具有最新 Validfrom日期的匹配来消除两者的歧义。

让我们试试这个来找到Validfrom正确行的日期。http://sqlfiddle.com/#!2/dff43/6/0这还给了 10 月 20 日。

SELECT MAX(Validfrom) AS Validfrom
  FROM ( SELECT STR_TO_DATE('2013-10-25', '%Y-%m-%d') AS thedate) d
  JOIN headertable
 WHERE headertable.Validfrom <= thedate
   AND headertable.Validto   >= thedate
   AND headertable.PICKUP LIKE '%NEW YORK%'
   AND headertable.DELIVERY LIKE '%CHICAGO%'

所以,现在我们必须使用这个日期找到给出“最佳”匹配的单行。这是如何做到这一点:http ://sqlfiddle.com/#!2/dff43/14/0

SELECT headertable.*
  FROM ( 
        SELECT STR_TO_DATE('2013-10-25', '%Y-%m-%d') AS thedate,
               '%NEW YORK%' AS PICKUP,
               '%CHICAGO%'  AS DELIVERY
       ) AS d
   JOIN headertable
  WHERE Validfrom <= thedate
    AND Validto   >= thedate
    AND PICKUP LIKE d.PICKUP
    AND DELIVERY LIKE d.DELIVERY
    AND ValidFrom IN  /* disambiguate */
      (
        SELECT MAX(Validfrom) AS Validfrom
          FROM headertable
         WHERE Validfrom <= thedate
           AND Validto   >= thedate
           AND PICKUP LIKE d.PICKUP
           AND DELIVERY LIKE d.DELIVERY
       )

这个查询有点像毛球。但是这里的业务规则也是如此。

最后,我们必须加入您的另一张桌子。与您的日期选择逻辑相比,这非常容易。http://sqlfiddle.com/#!2/dff43/17/0 我们将使用JOIN语法而不是逗号语法,因为它使查询逻辑更清晰。

SELECT headertable.*, linestable.*
  FROM ( 
        SELECT STR_TO_DATE('2013-10-25', '%Y-%m-%d') AS thedate,
               '%NEW YORK%' AS PICKUP,
               '%CHICAGO%'  AS DELIVERY
       ) AS d
   JOIN headertable
   JOIN linestable ON headertable.Id = linestable.headertableId
  WHERE Validto   >= thedate
    AND headertable.PICKUP LIKE d.PICKUP
    AND headertable.DELIVERY LIKE d.DELIVERY
    AND ValidFrom IN
      (
        SELECT MAX(Validfrom) AS Validfrom
          FROM headertable
         WHERE Validfrom <= thedate
           AND Validto   >= thedate
           AND PICKUP LIKE d.PICKUP
           AND DELIVERY LIKE d.DELIVERY
       )

这似乎也适用于您 2013 年 10 月 30 日的日期。 http://sqlfiddle.com/#!2/dff43/19/0

注意:我相信这个日期的模糊性表明您的业务规则存在问题。在我看来,您的 ValidFrom 和 ValidTo 日期可能不应该重叠。

于 2013-10-14T20:20:20.567 回答
1

要仅返回结果集中的第一条记录,请追加LIMIT 1到查询的末尾。

于 2013-10-14T11:30:56.663 回答
0

尝试这个

SELECT  * from schema1.headertable, schema1.linestable
WHERE headertable.Id= linestable.headertableId
AND STR_TO_DATE('" & thedate & "','%Y-%m-%d') between headertable.Validfrom and DATE_ADD(headertable.Validto, INTERVAL 1 DAY)
AND headertable.PICKUP LIKE '%NEW YORK%'
AND headertable.DELIVERY LIKE '%CHICAGO%'
ORDER BY headertable.Validfrom DESC, linestable.Id DESC

还要确保数据类型正确:Validfrom 和 ValidTo 应该是日期;thedate 应该是 Ymd 格式,例如。2013-10-14

于 2013-10-14T11:54:35.590 回答