Mysql在最近的日期(今天,昨天或之前)查询内部联接

时间:2015-05-23 07:06:28

标签: php mysql

我正在尝试从内部联接的表中提取最新的定价数据。价格全天更新,但不必在午夜更新。

当数据在当天结束时更新价格时,以下查询效果很好。但是,如果今天的数据是空白的,我如何得到昨天的数据?

我正在索引一个格式为date_itemnumber =>格式的列。 2015-05-22_12341234

SELECT h.*, collection.*, history.price
FROM collection
INNER JOIN h ON collection.itemid=h.id
INNER JOIN history ON collection.itemid=history.itemid 
AND concat('2015-05-23_',collection.itemid)=history.date_itemid
WHERE h.description LIKE '%Awesome%'
  

生产查询时间:.046秒

要清楚,我希望它检查该项目的最新记录。无论是今天,昨天还是之前。

SQLFiddle1

以下查询为我提供了所需的结果,但使用我的生产数据集返回结果需要3分钟。随着我的数据集变大,需要更长的时间。所以这不是最有效的方法。

SELECT h.*, collection.*, history.price
FROM collection
INNER JOIN h ON collection.itemid=h.id
INNER JOIN history ON collection.itemid=history.itemid 
AND (select history.date_itemid from history WHERE itemid=collection.itemid GROUP BY date_itemid DESC LIMIT 1)=history.date_itemid 
WHERE h.description LIKE '%Awesome%'
  

生产查询时间:181.140秒

SQLFiddle2

6 个答案:

答案 0 :(得分:3)

SELECT x.*
  FROM history x
  JOIN 
     ( SELECT itemid
            , MAX(date_itemid) max_date_itemid 
         FROM history 
  -- optional JOINS and WHERE here --
        GROUP
           BY itemid
     ) y
    ON y.itemid = x.itemid
   AND y.max_date_itemid = x.date_itemid;

http://sqlfiddle.com/#!9/975f5/13

答案 1 :(得分:1)

这应该有效:

SELECT h.*, collection.*, history.price
FROM collection
INNER JOIN h ON collection.itemid=h.id
INNER JOIN(
SELECT a.*
  FROM history a
  INNER JOIN 
     ( SELECT itemid,MAX(date_itemid) max_date_itemid
         FROM history 
        GROUP BY itemid
     ) b ON b.itemid = a.itemid AND b.max_date_itemid = a.date_itemid
  ) AS history ON history.itemid = collection.itemid
WHERE h.description LIKE '%Awesome%'

我不知道这是否需要大量的执行时间。请尝试一下,因为您的表中可能有更多数据,这将是查看查询执行时间的一个很好的测试。

答案 2 :(得分:0)

这实际上是SQL中一个相当普遍的问题,至少我觉得我遇到了很多问题。您要做的是加入一对多表,但只加入该表中最新或最旧的记录。

这样做的诀窍是在表上进行自我LEFT连接,记录许多记录,指定外键,并且id应该大于或小于其他记录' ID(或日期或您正在使用的任何内容)。然后在WHERE条件中,您只需添加一个条件,左连接表具有NULL ID - 它不能与更新的记录连接,因为它是最新的。

在您的情况下,SQL应该如下所示:

isAdmin

答案 3 :(得分:0)

这是另一种削减一个内连接语句的方法

select h.*,his.date_itemid, his.price from history his
INNER JOIN h ON his.itemid=h.id
WHERE his.itemid IN (select itemid from collection) AND h.description LIKE '%Awesome%' and his.id IN (select max(id) from history group by history.itemid)

你可以在这里试试http://sqlfiddle.com/#!9/837a8/1

答案 4 :(得分:0)

我不确定这是否是你想要的,但我试一试 编辑:修改

   CREATE VIEW LatestDatesforIds
AS
SELECT
  MAX(`history`.`date_itemid`) AS `lastPriceDate`,
  MAX(`history`.`id`) AS `matchingId`
FROM `history`
GROUP BY `history`.`itemid`;  


CREATE VIEW MatchDatesToPrices
AS
SELECT
  `ldi`.`lastPriceDate` AS `lastPriceDate`,
  `ldi`.`matchingId` AS `matchingId`,
  `h`.`id` AS `id`,
  `h`.`itemid` AS `itemid`,
  `h`.`price` AS `price`,
  `h`.`date_itemid` AS `date_itemid`
FROM (`LatestDatesforIds` `ldi`
  JOIN `history` `h`
    ON ((`ldi`.`matchingId` = `h`.`id`)));

SELECT c.itemid,price,lastpriceDate,description
FROM collection c
INNER JOIN MatchDatesToPrices mp
     ON c.itemid = mp.itemid
INNER JOIN h ON c.itemid = h.id

答案 5 :(得分:0)

难以在如此小的数据集上测试速度,但避免“分组依据”可能会加快速度。您可以尝试有条件地将历史表连接到自身而不是分组?

e.g。

SELECT h.*, c.*, h1.price
FROM h


INNER JOIN history h1 ON h1.itemid = h.id
LEFT OUTER JOIN history h2 ON h2.itemid = h.id
    AND h1.date_itemid < h2.date_itemid
INNER JOIN collection c ON c.itemid = h.id

WHERE h2.id IS NULL
AND h.description LIKE '%Awesome%'

更改此行

AND h1.date_itemid < h2.date_itemid

实际上在顺序索引字段(最好是唯一的)上工作也会加快速度。例如按ID ASC排序