【问题标题】:SQL SELECT QUERY BY DATESQL 按日期选择查询
【发布时间】:2013-10-15 04:20:20
【问题描述】:

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

这些是数据示例:

在 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 +linestable 中的链接汇率)

如果 thedate=10-oct-13,则显示选项 1。

如果 thedate=30-oct-13,则显示 2 条记录(Id 3 和 4)(区别在于 COMMODITY)

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

感谢任何帮助。

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

【问题讨论】:

  • 您在 HEADERTABLE 中有两条仅相差 VALIDFROM 的记录。您没有明确说明这一点,但您似乎想要检索 最近 VALIDFROM 日期在 thedate 或之前的记录。对吗?
  • 是的,你是对的,我可能没有正确解释自己,我已经修改了问题以包括承运人。日期必须介于 validfrom 和 validto always 之间,而不是 on 或之前。

标签: mysql date


【解决方案1】:

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

【讨论】:

  • 谢谢。几乎可以工作,但它只返回一条记录(headertable 上的 Id 2 链接到 linestable 中的 2 行,两者都应该显示,但只显示 1。
【解决方案2】:

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

首先,我们需要从您的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 参数放入查询中一次,并多次使用它。

但您的规范只需要其中一行,而不是两行。我们必须通过选择与 latest 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 日期可能不应该重叠。

【讨论】:

  • 谢谢,感谢您的详细回答。我花了几个小时让它工作,但我无法这样做。在您到 sqlfiddle.co 的链接中,如果您输入日期 2013-10-20,您会看到您只获得 UPS,而实际上应该显示 DHL 和 UPS,因为它们是两家不同的公司,都具有有效费率那个日期。尽管如此,我将继续使用您的代码,因为它正在朝着我追求的方向发展。
【解决方案3】:

试试这个

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 应该是日期;日期应采用 Y-m-d 格式,例如。 2013-10-14

【讨论】:

  • 谢谢,不幸的是,您的代码返回从 01-oct-13 到 20-oct-13 的所有费率(例如,如果 thedate=20-oct-13,它返回 01-oct 和 20-oct, id 1 和 2) 是的,日期是 Y-m-d 格式
  • 是的,那是因为给定 20-oct-13 的日期在 id 1 和 2 的范围内。您需要编辑到日期以免重叠或将结果数限制为 1通过添加“限制 1”和查询结束
  • 谢谢,这个想法是它只显示基于validfrom日期的最新记录。添加 LIMIT 1 有效,但仅显示行表中的一条记录,但在许多情况下,行表中有 2-10 个匹配行链接到表头表中的 1 条记录。
猜你喜欢
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-20
  • 2019-04-10
  • 2011-07-04
相关资源
最近更新 更多