(嵌套?)使用MAX和WHERE子句

时间:2016-11-08 21:12:59

标签: oracle select join nested max

我正在研究一组数据,以便从Oracle数据库生成报告。

数据分为两个表:

  1. SUPPLY
  2. 设备
  3. 只有一列链接两个表:

    • SUPPLY.DEVICE_ID
    • DEVICE.ID

    在供应中,有这些数据:( Markdown效果不佳。它应该显示一张表)

    | DEVICE_ID     | COLOR_TYPE    | SERIAL        | UNINSTALL_DATE        |
    |-----------    |------------   |-------------- |---------------------  |
    | 1232          | 1             | CAP857496     | 08/11/2016,19:10:50   |
    | 5263          | 2             | CAP57421      | 07/11/2016,11:20:00   |
    | 758           | 3             | CBO753421869  | 07/11/2016,04:25:00   |
    | 758           | 4             | CC9876543     | 06/11/2016,11:40:00   |
    | 8575          | 4             | CVF75421      | 05/11/2016,23:59:00   |
    | 758           | 4             | CAP67543      | 30/09/2016,11:00:00   |
    

    在DEVICE中,我可以选择所有列(或多或少),但每行都是唯一的。

    我需要达到的目标是: 对于每个SUPPLY.DEVICE_ID和SUPPLY.COLOR_TYPE,我需要最新的ROW - > MAX(UNINSTALL_DATE)

    加入 或多或少在DEVICE中的所有列。

    最后我应该有这样的事情:

    | ACCOUNT_CODE  | MODEL     | DEVICE.SERIAL     | DEVICE_ID     | COLOR_TYPE    | SUPPLY.SERIAL     | UNINSTALL_DATE        |
    |-------------- |-------    |---------------    |-----------    |------------   |---------------    |---------------------  |
    | BUSTO         | MS410     | LM753             | 1232          | 1             | CAP857496         | 08/11/2016,19:10:50   |
    | MACCHI        | MX310     | XC876             | 5263          | 2             | CAP57421          | 07/11/2016,11:20:00   |
    | ASL_COMO      | MX711     | AB123             | 758           | 3             | CBO753421869      | 07/11/2016,04:25:00   |
    | ASL_COMO      | MX711     | AB123             | 758           | 4             | CC9876543         | 06/11/2016,11:40:00   |
    | ASL_VARESE    | X950      | DE8745            | 8575          | 4             | CVF75421          | 05/11/2016,23:59:00   |
    

    到目前为止,使用嵌套的选择如:

    SELECT DEVICE_ID,COLOR_TYPE,SERIAL,UNINSTALL_DATE FROM 
    (SELECT SELECT DEVICE_ID,COLOR_TYPE,SERIAL,UNINSTALL_DATE 
    FROM SUPPLY WHERE DEVICE_ID = '123456' ORDER BY UNINSTALL_DATE DESC) 
    WHERE ROWNUM <= 1
    

    在尝试MAX(UNISTALL_DATE) or HIGHEST(UNISTALL_DATE)后,我设法在UNISTALL_DATE列上获得了最高价值。

    我也试过了:

    SELECT SUPPLY.DEVICE_ID, SUPPLY.COLOR_TYPE, .... 
    FROM SUPPLY,DEVICE WHERE SUPPLY.DEVICE_ID = DEVICE.ID
    

    它有效,但给了我所有的项目,基本上它是两个表的合并。 当我尝试缩小所选数据的范围时,我会收到错误或结果为空。

    我开始怀疑它无法获取这些数据并且我开始在excel中导出数据并从那里开始工作,但我希望有人可以在给予之前帮助我向上...

    提前谢谢。

3 个答案:

答案 0 :(得分:0)

  

对于每个SUPPLY.DEVICE_ID和SUPPLY.COLOR_TYPE,我需要最新的ROW - &gt; MAX(UNINSTALL_DATE)

以这种方式使用ROW_NUMBER功能:

SELECT s.*,
       row_number() OVER (
             PARTITION BY DEVICE_ID, COLOR_TYPE
             ORDER BY UNINSTALL_DATE DESC
       ) As RN
FROM SUPPLY s

此查询标记RN = 1

的最新行
  

或多或少地加入DEVICE中的所有列。

只需将上述查询加入DEVICE表

即可
SELECT d.*, 
       x.COLOR_TYPE,
       x.SERIAL,
       x.UNINSTALL_DATE
FROM (
   SELECT s.*,
          row_number() OVER (
                PARTITION BY DEVICE_ID, COLOR_TYPE
                ORDER BY UNINSTALL_DATE DESC
          ) As RN
   FROM SUPPLY s
) x
JOIN DEVICE d
ON d.DEVICE_ID = x.DEVICE_ID AND x.RN=1

答案 1 :(得分:0)

好的 - 所以你也可以按device_id, color_typeselect max(uninstall_date)进行分组,然后加入另一个表。但是您会错过最近一行的serial值(对于device_id, color_type的每个组合)。

有几种方法可以解决这个问题。您对rownum的尝试很接近,但问题是您需要在每个&#34;组内订购&#34; (按device_id, color_type)并从每个组中获取第一行。我相信有人会使用row_number()rank()max(uninstall_date)的分析版本发布这些行的解决方案。

当你需要&#34; top&#34;每组中的一行,您可以使用keep (dense_rank first/last) - 这可能会稍微提高效率 - 如下所示:

select   device_id, color_type, 
         max(serial) keep (dense_rank last order by uninstall_date) as serial, 
         max(uninstall_date) as uninstall_date
from     supply
group by device_id, color_type
;

然后加入另一个表。注意:dense_rank last将为每个组选取最近(最长)日期的行或行。如果有联系,那就是不止一行;然后,serial将是具有最新日期的那些行中的最大值(按字典顺序排列)。您也可以选择min,或者添加一些订单以便选择一个特定的订单(您没有讨论这种可能性)。

答案 2 :(得分:0)

SELECT 
      d.ACCOUNT_CODE, d.DNS_HOST_NAME,d.IP_ADDRESS,d.MODEL_NAME,d.OVERRIDE_SERIAL_NUMBER,d.SERIAL_NUMBER,
      s.COLOR, s.SERIAL_NUMBER, s.UNINSTALL_TIME
FROM (
      SELECT s.DEVICE_ID, s.LAST_LEVEL_READ, s.SERIAL_NUMBER,TRUNC(s.UNINSTALL_TIME), row_number() 
OVER (
      PARTITION BY DEVICE_ID, COLOR
      ORDER BY UNINSTALL_TIME DESC
      ) As RN
FROM SUPPLY s 
WHERE s.UNINSTALL_TIME IS NOT NULL AND s.SERIAL_NUMBER IS NOT NULL
        )

JOIN DEVICE d
ON d.ID = s.DEVICE_ID AND s.RN=1;

@krokodilko:非常感谢你的帮助。第一个查询有效。修改它以删除垃圾,把我需要的真实列名称(昨天晚上我无法访问数据库)并获得我需要的数据。

不幸的是,当我按照你的建议加入这两个表时,我得到了错误:

  

ORA-00904:&#34; S&#34;。&#34; RN&#34;:无效的标识符   00904. 00000 - &#34;%s:无效的标识符&#34;

如果我删除s。在RN之前,ORA-00904移回s.DEVICE_ID。