选择具有最大值的行进行连接

时间:2014-11-17 15:51:33

标签: sql join aggregation min firebird2.5

这可能是非常简单的事情,但是我在这个陈述上工作了将近一天,我无法以某种方式完成任务。

我想做的是为每个存储地点提供最年轻的匹配包裹订单。

STORAGEPLACE(    ID,    STORAGE_ZONE,    值a)

PARCELORDER    (ID,    架,    时间结束,    VALUEB)

Storagezone和Shelf属于同一类型。

可以有多个匹配的存储空间和多个包裹,这就是为什么我需要具有最小值的存储空间。

VALUEA和VALUEB只是附加值。

SELECT  p1.NAME, t1.ID, t1.ENDTIME
    FROM STORAGE_PLACE p1
    LEFT JOIN PARCELORDER t1
    ON p1.STORAGE_ZONE=t1.SHELF
    INNER JOIN( SELECT ta.ID, MIN(ta.ENDTIME) as mindate
                from PARCELORDER ta
                GROUP BY ta.ID) tb
    ON tb.ID = t1.ID and tb.mindate = t1.ENDTIME 
    WHERE p1.VALUEA = 0  AND t1.VALUEB = -1

我尝试了几个连接,(自然,左,内......),这些连接都会导致storage_places和parcelorders的多种组合。

我也尝试过的是

SELECT  p1.NAME, t1.ID, t1.ENDTIME
    FROM STORAGE_PLACE p1
    LEFT JOIN PARCELORDER t1
    ON p1.STORAGE_ZONE=t1.SHELF
    INNER JOIN( SELECT DISTINCT(ta.ID), MIN(ta.ENDTIME) as mindate
                from PARCELORDER ta
                GROUP BY ta.ID) tb
    ON tb.ID = t1.ID and tb.mindate = t1.ENDTIME 
    WHERE p1.VALUEA = 0  AND t1.VALUEB = -1

SELECT  p1.NAME, t1.ID, t1.ENDTIME
    FROM STORAGE_PLACE p1
    LEFT JOIN PARCELORDER t1
    ON p1.STORAGE_ZONE=t1.SHELF
    INNER JOIN( SELECT FIRST 1 ta.ID, MIN(ta.ENDTIME) as mindate
                from PARCELORDER ta
                GROUP BY ta.ID) tb
    ON tb.ID = t1.ID and tb.mindate = t1.ENDTIME 
    WHERE p1.VALUEA = 0  AND t1.VALUEB = -1

以及它们的几种组合,但那些只返回第一个包裹的所有组合。

我正在使用较旧的firebird,因此SELECT ONE Row with the MAX() value on a column中某处描述的row_number()方法将无效。

2 个答案:

答案 0 :(得分:2)

查看您的架构,我猜这是与PAREL中的SHELF的一对多关系,是STORAGE_PLACE中STORAGE_ZONE的外键。您的查询正在对PARCELORDER的ID进行分组,我猜测它是表中的主键,因此您仍然可以获得表中每条记录的一条记录。

你想要做的是按SHELF分组,这样每个SHELF只能获得一条记录。

尝试此查询:

SELECT  p1.NAME, t1.ID, t1.ENDTIME
    FROM STORAGE_PLACE p1
    INNER JOIN( SELECT ta.SHELF, MIN(ta.ENDTIME) as mindate
                from PARCELORDER ta
                GROUP BY ta.SHELF) tb
    ON p1.STORAGE_ZONE=t1.SHELF 
    INNER JOIN PARCELORDER t1 ON t1.ENDTIME = tb.mindate AND t1.SHELF = tb.SHELF
WHERE p1.VALUEA = 0  AND t1.VALUEB = -1

假设PARCELORDER中只有一条记录用于给定的SHELF和ENDTIME,这应该对你有用。否则,您可能必须使用给定SHELF的最小ENDTIME记录的ID创建临时表。

答案 1 :(得分:0)

我很难说这两个表是如何相关的,因为除了在不起作用的查询中,你没有提供这些信息,因此我们试图从你的查询中解读这些关系也可能不正确。也就是说,试试这个。如果它不起作用,我将需要了解有关两个表中的行如何相关的更多详细信息,最好是样本数据:

with CTE_MIN_TIME_PER_SHELF as (
  select   SHELF, min( ENDTIME ) as MIN_ENDTIME
  from     PARCELORDER
  group by SHELF
)
select     p1.NAME, t1.ID, c.MIN_ENDTIME
from       STORAGE_PLACE p1
left join  CTE_MIN_TIME_PER_SHELF c
      on   c.SHELF    = p1.STORAGE_ZONE
left join  PARCELORDER t1
      on   t1.SHELF   = c.SHELF
      and  t1.ENDTIME = c.MIN_ENDTIME

我不知道VALUEA和VALUEB来自哪个部分。这是Firebird的事吗?:

 WHERE p1.VALUEA = 0 AND t1.VALUEB= -1