ORA-00904 "invalid identifier" 但查询中存在标识符
ORA-00904 "invalid identifier" but identifier exists in query
我在故障报告 Oracle 数据库中工作,试图从中获取故障信息。
我查询的主要table是事件,包括事件信息。 Incident 中的每条记录在 WorkOrder table(或 none)中可能有任意数量的记录,并且 WorkOrder 中的每条记录在 WorkLog table(或[=84]中可能有任意数量的记录=]).
此时我要做的是,对于事件中的每条记录,在 MXRONSITE 字段中找到具有最小值的工作日志,并且对于该工作日志,return MXRONSITE 时间和来自工单的 REPORTDATE。我使用 MIN 子查询完成了此操作,但事实证明多个工作日志可能具有相同的 MXRONSITE 时间,因此我拉回了比我想要的更多的记录。我试图为它创建一个子子查询,但它现在说我在 WHERE 行中的 WOL1.WONUM 有一个无效的标识符 (ORA-00904),即使该标识符在其他地方正在使用。
感谢任何帮助。请注意,查询中还有其他内容,但查询的其余部分是独立工作的,但这在完整查询中或单独工作时不起作用。
SELECT
WL1.MXRONSITE as "Date_First_Onsite",
WOL1.REPORTDATE as "Date_First_Onsite_Notified"
FROM Maximo.Incident
LEFT JOIN (Maximo.WorkOrder WOL1
LEFT JOIN Maximo.Worklog WL1
ON WL1.RECORDKEY = WOL1.WONUM)
ON WOL1.ORIGRECORDID = Incident.TICKETID
AND WOL1.ORIGRECORDCLASS = 'INCIDENT'
WHERE (WL1.WORKLOGID IN
(SELECT MIN(WL3.WORKLOGID)
FROM (SELECT MIN(WL3.MXRONSITE), WL3.WORKLOGID
FROM Maximo.Worklog WL3 WHERE WOL1.WONUM = WL3.RECORDKEY))
or WL1.WORKLOGID is null)
澄清一下,我想要的是:
- 对于事件中的每个故障,
- 工作日志中最早的 MXRONSITE table(如果存在这样的值),
- 对于该工作日志,来自 WorkOrder table 的关联记录的信息。
具有多个工作订单的事件记录和具有多个工作日志的工作订单可能具有相同的 MXRONSITE 时间,这使情况变得复杂。
经过一些试验,我找到了一个(几乎)可行的解决方案:
WITH WLONSITE as (
SELECT
MIN(WLW.MXRONSITE) as "ONSITE",
WLWOW.ORIGRECORDID as "TICKETID",
WLWOW.WONUM as "WONUM"
FROM
MAXIMO.WORKLOG WLW
INNER JOIN
MAXIMO.WORKORDER WLWOW
ON
WLW.RECORDKEY = WLWOW.WONUM
WHERE
WLWOW.ORIGRECORDCLASS = 'INCIDENT'
GROUP BY
WLWOW.ORIGRECORDID, WLWOW.WONUM
)
select
incident.ticketid,
wlonsite.onsite,
wlonsite.wonum
from
maximo.incident
LEFT JOIN WLONSITE
ON WLONSITE.TICKETID = Incident.TICKETID
WHERE
(WLONSITE.ONSITE is null or WLONSITE.ONSITE = (SELECT MIN(WLONSITE.ONSITE) FROM WLONSITE WHERE WLONSITE.TICKETID = Incident.TICKETID AND ROWNUM=1))
AND Incident.AFFECTEDDATE >= TO_DATE ('01/12/2015', 'DD/MM/YYYY')
然而,这要慢得多,而且仍然不太正确,因为事实证明,一个事件可以有多个具有相同 ONSITE 时间的工单(aaargh!)。
根据要求,这是一个示例输入,以及我想从中得到的信息(对格式表示歉意)。请注意,虽然 TICKETID 和 WONUM 是主键,但它们是字符串而不是整数。 WORKLOGID 是一个整数。
事件table:
TICKETID / 说明 / FieldX
1 / WORD1 / S
2 / WORD2 / P
3 / WORDX /
4 // 问
工单table:
WONUM / ORIGRECORDID / 报告日期
11 / 1 / 2015-01-01
12 / 2 / 2015-01-01
13 / 2 / 2015-02-04
14 / 3 / 2015-04-05
工作日志table:
WORKLOGID / RECORDKEY / MXRONSITE
101 / 11 / 2015-01-05
102 / 12 / 2015-01-04
103 / 12 /
104 / 12 / 2015-02-05
105 / 13 /
输出:
TICKETID / WONUM / WORKLOGID
1 / 11 / 101
2 / 12 / 102
3 / /
4 / /
(工作日志 101 链接到 TICKETID 1,具有非空 MXRONSITE,并且来自工作订单 11)
(工作日志 102-105 链接到 TICKETID 2,其中 102 具有最低的 MXRONSITE,并且是工作订单 12)
(没有与故障 103 或 104 关联的工作日志,因此工作订单和工作日志字段为空)
Post圣诞节来袭!
我找到了一个有效的解决方案:
我找到的方法是使用多个WITH查询,如下:
WLMINL AS (
SELECT
RECORDKEY, MXRONSITE, MIN(WORKLOGID) AS "WORKLOG"
FROM MAXIMO.WORKLOG
WHERE WORKLOG.CLASS = 'WORKORDER'
GROUP BY RECORDKEY, MXRONSITE
),
WLMIND AS (
SELECT
RECORDKEY, MIN(MXRONSITE) AS "MXRONSITE"
FROM MAXIMO.WORKLOG
WHERE WORKLOG.CLASS = 'WORKORDER'
GROUP BY RECORDKEY
),
WLMIN AS (
SELECT
WLMIND.RECORDKEY AS "WONUM", WLMIND.MXRONSITE AS "ONSITE", WLMINL.WORKLOG AS "WORKLOGID"
FROM
WLMIND
INNER JOIN
WLMINL
ON
WLMIND.RECORDKEY = WLMINL.RECORDKEY AND WLMIND.MXRONSITE = WLMINL.MXRONSITE
)
因此对于每个工作订单找到第一个日期,然后对于每个工作订单和日期找到最低的 worklogid,然后加入两个 tables。然后在更高级别重复此操作以按事件查找数据。
然而,这种方法在合理的时间内不起作用,所以虽然它可能适用于较小的数据库table,但对我正在使用的庞然大物却不利。
嵌套子查询时,不能访问属于上两级或更多级的列;在您的声明中,WL1 在最里面的子查询中不可访问。 (顺便说一句,还缺少一个 group-by 子句)
这可能有效(不确定您期望的输出结果,但请尝试一下):
SELECT
WL1.MXRONSITE as "Date_First_Onsite",
WOL1.REPORTDATE as "Date_First_Onsite_Notified"
FROM Maximo.Incident
LEFT JOIN (
Maximo.WorkOrder WOL1
LEFT JOIN Maximo.Worklog WL1
ON WL1.RECORDKEY = WOL1.WONUM
) ON WOL1.ORIGRECORDID = Incident.TICKETID
AND WOL1.ORIGRECORDCLASS = 'INCIDENT'
WHERE WL1.WORKLOGID =
( SELECT MIN(WL3.WORKLOGID)
FROM Maximo.WorkOrder WOL3
LEFT JOIN Maximo.Worklog WL3
ON WL3.RECORDKEY = WOL3.WONUM
WHERE WOL3.ORIGRECORDID = WOL1.ORIGRECORDID
AND WL3.MXRONSITE IS NOT NULL
)
OR WL1.WORKLOGID IS NULL AND NOT EXISTS
( SELECT MIN(WL4.WORKLOGID)
FROM Maximo.WorkOrder WOL4
LEFT JOIN Maximo.Worklog WL4
ON WL4.RECORDKEY = WOL4.WONUM
WHERE WOL4.ORIGRECORDID = WOL1.ORIGRECORDID
AND WL4.MXRONSITE IS NOT NULL )
我可能不了解您要执行的操作的详细信息...如果您有一些示例输入和所需的输出,那将是一个很大的帮助。
就是说,我认为分析函数会有很大帮助,不仅在获取输出方面而且在组织代码方面。下面是如何在子查询中使用 max
分析函数的示例。
同样,有关连接的详细信息可能已关闭 -- 如果您可以提供一些示例输入和输出,我敢打赌有人可以到达您想要去的地方:
with wo as (
select
wonum, origrecordclass, origrecordid, reportdate,
max (reportdate) over (partition by origrecordid) as max_date
from Maximo.workorder
where origrecordclass = 'INCIDENT'
),
logs as (
select
worklogid, mxronsite, recordkey,
max (mxronsite) over (partition by recordkey) as max_mx
from Maximo.worklog
)
select
i.ticketid,
l.mxronsite as "Date_First_Onsite",
wo.reportdate as "Date_First_Onsite_Notified"
from
Maximo.incident i
left join wo on
wo.origrecordid = i.ticketid and
wo.reportdate = wo.max_date
left join logs l on
wo.wonum = l.recordkey and
l.mxronsite = l.max_mx
-- 编辑--
根据您的示例输入和所需的输出,这似乎可以提供所需的结果。它确实在子查询中做了一些爆炸,但希望分析函数的效率会抑制它。与使用 group by 相比,它们通常要快得多:
with wo_logs as (
select
wo.wonum, wo.origrecordclass, wo.origrecordid, wo.reportdate,
l.worklogid, l.mxronsite, l.recordkey,
max (reportdate) over (partition by origrecordid) as max_date,
min (mxronsite) over (partition by recordkey) as min_mx
from
Maximo.workorder wo
left join Maximo.worklog l on wo.wonum = l.recordkey
where wo.origrecordclass = 'INCIDENT'
)
select
i.ticketid, wl.wonum, wl.worklogid,
wl.mxronsite as "Date_First_Onsite",
wl.reportdate as "Date_First_Onsite_Notified"
from
Maximo.incident i
left join wo_logs wl on
i.ticketid = wl.origrecordid and
wl.mxronsite = wl.min_mx
order by 1
我会用 row_number
函数来做到这一点:
select ticketid, case when worklogid is not null then reportdate end d1, mxronsite d2
from (
select i.ticketid, wo.reportdate, wl.mxronsite, wo.wonum, wl.worklogid,
row_number() over (partition by i.ticketid
order by wl.mxronsite, wo.reportdate) rn
from incident i
left join workorder wo on wo.origrecordid = i.ticketid
and wo.origrecordclass = 'INCIDENT'
left join worklog wl on wl.recordkey = wo.wonum )
where rn = 1 order by ticketid
我在故障报告 Oracle 数据库中工作,试图从中获取故障信息。
我查询的主要table是事件,包括事件信息。 Incident 中的每条记录在 WorkOrder table(或 none)中可能有任意数量的记录,并且 WorkOrder 中的每条记录在 WorkLog table(或[=84]中可能有任意数量的记录=]).
此时我要做的是,对于事件中的每条记录,在 MXRONSITE 字段中找到具有最小值的工作日志,并且对于该工作日志,return MXRONSITE 时间和来自工单的 REPORTDATE。我使用 MIN 子查询完成了此操作,但事实证明多个工作日志可能具有相同的 MXRONSITE 时间,因此我拉回了比我想要的更多的记录。我试图为它创建一个子子查询,但它现在说我在 WHERE 行中的 WOL1.WONUM 有一个无效的标识符 (ORA-00904),即使该标识符在其他地方正在使用。
感谢任何帮助。请注意,查询中还有其他内容,但查询的其余部分是独立工作的,但这在完整查询中或单独工作时不起作用。
SELECT
WL1.MXRONSITE as "Date_First_Onsite",
WOL1.REPORTDATE as "Date_First_Onsite_Notified"
FROM Maximo.Incident
LEFT JOIN (Maximo.WorkOrder WOL1
LEFT JOIN Maximo.Worklog WL1
ON WL1.RECORDKEY = WOL1.WONUM)
ON WOL1.ORIGRECORDID = Incident.TICKETID
AND WOL1.ORIGRECORDCLASS = 'INCIDENT'
WHERE (WL1.WORKLOGID IN
(SELECT MIN(WL3.WORKLOGID)
FROM (SELECT MIN(WL3.MXRONSITE), WL3.WORKLOGID
FROM Maximo.Worklog WL3 WHERE WOL1.WONUM = WL3.RECORDKEY))
or WL1.WORKLOGID is null)
澄清一下,我想要的是:
- 对于事件中的每个故障,
- 工作日志中最早的 MXRONSITE table(如果存在这样的值),
- 对于该工作日志,来自 WorkOrder table 的关联记录的信息。
具有多个工作订单的事件记录和具有多个工作日志的工作订单可能具有相同的 MXRONSITE 时间,这使情况变得复杂。
经过一些试验,我找到了一个(几乎)可行的解决方案:
WITH WLONSITE as (
SELECT
MIN(WLW.MXRONSITE) as "ONSITE",
WLWOW.ORIGRECORDID as "TICKETID",
WLWOW.WONUM as "WONUM"
FROM
MAXIMO.WORKLOG WLW
INNER JOIN
MAXIMO.WORKORDER WLWOW
ON
WLW.RECORDKEY = WLWOW.WONUM
WHERE
WLWOW.ORIGRECORDCLASS = 'INCIDENT'
GROUP BY
WLWOW.ORIGRECORDID, WLWOW.WONUM
)
select
incident.ticketid,
wlonsite.onsite,
wlonsite.wonum
from
maximo.incident
LEFT JOIN WLONSITE
ON WLONSITE.TICKETID = Incident.TICKETID
WHERE
(WLONSITE.ONSITE is null or WLONSITE.ONSITE = (SELECT MIN(WLONSITE.ONSITE) FROM WLONSITE WHERE WLONSITE.TICKETID = Incident.TICKETID AND ROWNUM=1))
AND Incident.AFFECTEDDATE >= TO_DATE ('01/12/2015', 'DD/MM/YYYY')
然而,这要慢得多,而且仍然不太正确,因为事实证明,一个事件可以有多个具有相同 ONSITE 时间的工单(aaargh!)。
根据要求,这是一个示例输入,以及我想从中得到的信息(对格式表示歉意)。请注意,虽然 TICKETID 和 WONUM 是主键,但它们是字符串而不是整数。 WORKLOGID 是一个整数。
事件table:
TICKETID / 说明 / FieldX
1 / WORD1 / S
2 / WORD2 / P
3 / WORDX /
4 // 问
工单table:
WONUM / ORIGRECORDID / 报告日期
11 / 1 / 2015-01-01
12 / 2 / 2015-01-01
13 / 2 / 2015-02-04
14 / 3 / 2015-04-05
工作日志table:
WORKLOGID / RECORDKEY / MXRONSITE
101 / 11 / 2015-01-05
102 / 12 / 2015-01-04
103 / 12 /
104 / 12 / 2015-02-05
105 / 13 /
输出:
TICKETID / WONUM / WORKLOGID
1 / 11 / 101
2 / 12 / 102
3 / /
4 / /
(工作日志 101 链接到 TICKETID 1,具有非空 MXRONSITE,并且来自工作订单 11)
(工作日志 102-105 链接到 TICKETID 2,其中 102 具有最低的 MXRONSITE,并且是工作订单 12)
(没有与故障 103 或 104 关联的工作日志,因此工作订单和工作日志字段为空)
Post圣诞节来袭!
我找到了一个有效的解决方案:
我找到的方法是使用多个WITH查询,如下:
WLMINL AS (
SELECT
RECORDKEY, MXRONSITE, MIN(WORKLOGID) AS "WORKLOG"
FROM MAXIMO.WORKLOG
WHERE WORKLOG.CLASS = 'WORKORDER'
GROUP BY RECORDKEY, MXRONSITE
),
WLMIND AS (
SELECT
RECORDKEY, MIN(MXRONSITE) AS "MXRONSITE"
FROM MAXIMO.WORKLOG
WHERE WORKLOG.CLASS = 'WORKORDER'
GROUP BY RECORDKEY
),
WLMIN AS (
SELECT
WLMIND.RECORDKEY AS "WONUM", WLMIND.MXRONSITE AS "ONSITE", WLMINL.WORKLOG AS "WORKLOGID"
FROM
WLMIND
INNER JOIN
WLMINL
ON
WLMIND.RECORDKEY = WLMINL.RECORDKEY AND WLMIND.MXRONSITE = WLMINL.MXRONSITE
)
因此对于每个工作订单找到第一个日期,然后对于每个工作订单和日期找到最低的 worklogid,然后加入两个 tables。然后在更高级别重复此操作以按事件查找数据。
然而,这种方法在合理的时间内不起作用,所以虽然它可能适用于较小的数据库table,但对我正在使用的庞然大物却不利。
嵌套子查询时,不能访问属于上两级或更多级的列;在您的声明中,WL1 在最里面的子查询中不可访问。 (顺便说一句,还缺少一个 group-by 子句)
这可能有效(不确定您期望的输出结果,但请尝试一下):
SELECT
WL1.MXRONSITE as "Date_First_Onsite",
WOL1.REPORTDATE as "Date_First_Onsite_Notified"
FROM Maximo.Incident
LEFT JOIN (
Maximo.WorkOrder WOL1
LEFT JOIN Maximo.Worklog WL1
ON WL1.RECORDKEY = WOL1.WONUM
) ON WOL1.ORIGRECORDID = Incident.TICKETID
AND WOL1.ORIGRECORDCLASS = 'INCIDENT'
WHERE WL1.WORKLOGID =
( SELECT MIN(WL3.WORKLOGID)
FROM Maximo.WorkOrder WOL3
LEFT JOIN Maximo.Worklog WL3
ON WL3.RECORDKEY = WOL3.WONUM
WHERE WOL3.ORIGRECORDID = WOL1.ORIGRECORDID
AND WL3.MXRONSITE IS NOT NULL
)
OR WL1.WORKLOGID IS NULL AND NOT EXISTS
( SELECT MIN(WL4.WORKLOGID)
FROM Maximo.WorkOrder WOL4
LEFT JOIN Maximo.Worklog WL4
ON WL4.RECORDKEY = WOL4.WONUM
WHERE WOL4.ORIGRECORDID = WOL1.ORIGRECORDID
AND WL4.MXRONSITE IS NOT NULL )
我可能不了解您要执行的操作的详细信息...如果您有一些示例输入和所需的输出,那将是一个很大的帮助。
就是说,我认为分析函数会有很大帮助,不仅在获取输出方面而且在组织代码方面。下面是如何在子查询中使用 max
分析函数的示例。
同样,有关连接的详细信息可能已关闭 -- 如果您可以提供一些示例输入和输出,我敢打赌有人可以到达您想要去的地方:
with wo as (
select
wonum, origrecordclass, origrecordid, reportdate,
max (reportdate) over (partition by origrecordid) as max_date
from Maximo.workorder
where origrecordclass = 'INCIDENT'
),
logs as (
select
worklogid, mxronsite, recordkey,
max (mxronsite) over (partition by recordkey) as max_mx
from Maximo.worklog
)
select
i.ticketid,
l.mxronsite as "Date_First_Onsite",
wo.reportdate as "Date_First_Onsite_Notified"
from
Maximo.incident i
left join wo on
wo.origrecordid = i.ticketid and
wo.reportdate = wo.max_date
left join logs l on
wo.wonum = l.recordkey and
l.mxronsite = l.max_mx
-- 编辑--
根据您的示例输入和所需的输出,这似乎可以提供所需的结果。它确实在子查询中做了一些爆炸,但希望分析函数的效率会抑制它。与使用 group by 相比,它们通常要快得多:
with wo_logs as (
select
wo.wonum, wo.origrecordclass, wo.origrecordid, wo.reportdate,
l.worklogid, l.mxronsite, l.recordkey,
max (reportdate) over (partition by origrecordid) as max_date,
min (mxronsite) over (partition by recordkey) as min_mx
from
Maximo.workorder wo
left join Maximo.worklog l on wo.wonum = l.recordkey
where wo.origrecordclass = 'INCIDENT'
)
select
i.ticketid, wl.wonum, wl.worklogid,
wl.mxronsite as "Date_First_Onsite",
wl.reportdate as "Date_First_Onsite_Notified"
from
Maximo.incident i
left join wo_logs wl on
i.ticketid = wl.origrecordid and
wl.mxronsite = wl.min_mx
order by 1
我会用 row_number
函数来做到这一点:
select ticketid, case when worklogid is not null then reportdate end d1, mxronsite d2
from (
select i.ticketid, wo.reportdate, wl.mxronsite, wo.wonum, wl.worklogid,
row_number() over (partition by i.ticketid
order by wl.mxronsite, wo.reportdate) rn
from incident i
left join workorder wo on wo.origrecordid = i.ticketid
and wo.origrecordclass = 'INCIDENT'
left join worklog wl on wl.recordkey = wo.wonum )
where rn = 1 order by ticketid