我正在研究一组数据,以便从Oracle数据库生成报告。
数据分为两个表:
只有一列链接两个表:
在供应中,有这些数据:( 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中导出数据并从那里开始工作,但我希望有人可以在给予之前帮助我向上...
提前谢谢。
答案 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_type
和select 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。