选择按3列分组的最新记录

时间:2018-03-29 23:06:12

标签: mysql greatest-n-per-group

我正在尝试返回按ItemNumFeeSched分组的最新记录的价格,Customer可以取消。我无法理解如何合理地做到这一点。

问题在于我正在加入包含数十万行的5个表,最终得到这个结果集。初始查询大约需要一分钟才能运行,并且过去存在一些超时错误问题。由于这将在客户端的工作站上运行,它可能运行得更慢,我无权修改服务器设置以增加内存/超时。

这是我的数据:

Customer        Price            ItemNum           FeeSched             Date
   5            70.75             01202               12             12-06-2017
   5            70.80             01202               12             06-07-2016
   5            70.80             01202               12             07-21-2017
   5            70.80             01202               12             10-26-2016
   5            82.63             02144               61             12-06-2017
   5            84.46             02144               61             06-07-2016
   5            84.46             02144               61             07-21-2017
   5            84.46             02144               61             10-26-2016

我无权创建临时表或视图,并且在C树中没有@variable这样的东西,但在大多数情况下它都像MySql一样。我想使用GROUP BY ItemNum, FeeSched之类的内容并选择MAX(Date)。问题是,除非我将Price放入GROUP BY,否则我会收到错误。

我可以再次运行查询,只选择ItemNum, FeeSched, Date,然后执行INNER JOIN,但每次查询花一分钟时间,似乎有一种更好的方式,也许我不会知道。

这是我正在运行的查询,除了处理的数据量之外,查询并不是那么复杂。最终结果约为50,000行。我不能分享很多关于数据库结构的内容,因为它包含在NDA中。

SELECT DISTINCT 
CustomerNum,
paid as Price,
ItemNum,
n.pdate as newest
from admin.fullproclog as f
    INNER JOIN ( 
        SELECT 
               id,
               itemId,
               MAX(TO_CHAR(pdate, 'MM-DD-YYYY')) as pdate
        from admin.fullproclog 
        WHERE pdate > timestampadd(sql_tsi_year, -3, NOW())
        group by id, itemId
    ) as n ON n.id = f.id AND n.itemId = f.itemId AND n.pdate = f.pdate

    LEFT join (SELECT itemId AS linkid, ItemNum FROM   admin.itemlist) AS codes ON codes.linkid = f.itemId AND ItemNum >0
    INNER join (SELECT DISTINCT parent_id, 
                   MAX(ins1.feesched) as CustomerNum
    FROM   admin.customers AS p 
          left join admin.feeschedule AS ins1 
                 ON ins1.feescheduleid = p.primfeescheduleid 
          left join admin.group AS c1 
                 ON c1.insid = ins1.feesched 
    WHERE status =1
                 GROUP BY parent_id) 
      AS ip ON ip.parent_id = f.parent_id 

WHERE CustomerNum >0 AND ItemNum >0
UNION ALL

SELECT DISTINCT 
CustomerNum,
secpaid as Price,
ItemNum,
n.pdate as newest
from admin.fullproclog as f
    INNER JOIN ( 
        SELECT 
               id,
               itemId,
               MAX(TO_CHAR(pdate, 'MM-DD-YYYY')) as pdate
        from admin.fullproclog 
        WHERE pdate > timestampadd(sql_tsi_year, -3, NOW())
        group by id, itemId
    ) as n ON n.id = f.id AND n.itemId = f.itemId AND n.pdate = f.pdate

    LEFT join (SELECT itemId AS linkid, ItemNum FROM   admin.itemlist) AS codes ON codes.linkid = f.itemId AND ItemNum >0
    INNER join (SELECT DISTINCT parent_id, 
                   MAX(ins1.feesched) as CustomerNum
    FROM   admin.customers AS p 
          left join admin.feeschedule AS ins1 
                 ON ins1.feescheduleid = p.secfeescheduleid 
          left join admin.group AS c1 
                 ON c1.insid = ins1.feesched 
    WHERE status =1
                 GROUP BY parent_id) 
      AS ip ON ip.parent_id = f.parent_id 

WHERE CustomerNum >0  AND ItemNum >0 

2 个答案:

答案 0 :(得分:2)

当我阅读前三段时,我觉得很简单,但当我读完整个问题时,我感到有些困惑。

无论您采取了哪些措施来获取上面发布的数据,一旦您获得了这样的数据,就可以轻松地检索“按ItemNumFeeSched分组的最新记录”。

如何:

  • 首先,按Date DESC。
  • 对整个结果集进行排序
  • 其次,从排序结果集中选择您需要的字段,并按ItemNumFeeSched分组,而不使用任何汇总方法。

因此,查询可能是这样的:

SELECT t.Price, t.ItemNum, t.FeeSched, t.Date 
FROM (SELECT * FROM table ORDER BY Date DESC) AS t 
GROUP BY t.ItemNum, t.FeeSched;

工作原理:

当您的数据被分组并且您选择没有聚合方法的行时,它将仅返回每个组的第一行。由于您在分组之前已对所有行进行了排序,因此第一行将完全是“最新记录”。

如果您在使用此方法时遇到任何问题或错误,请与我联系。

答案 1 :(得分:0)

你也可以尝试这样:

Select Price, ItemNum, FeeSched, Date from table where Date IN (Select MAX(Date) from table group by ItemNum, FeeSched,Customer);

内部sql查询按ItemNum返回最大日期组,FeeSched和IN语句仅获取具有最大日期的记录。