我有一个Oracle 11数据库表,可以跟踪每个部门的库存项目状态。
ITEM_NUMBER DEPT_NO STATUS ----------- --------- --------- 1 AAA OK 2 AAA OK 3 AAA MISSING 4 BBB OK 5 BBB OK 6 AAA OK 7 AAA OK
我想创建一个视图,按部门和状态显示每个项目范围。如果范围内的任何项目都是MISSING,则状态应为MISSING,否则应该没问题。
在上面的示例中,视图输出应为:
START END DEPT_NO STATUS ------ ----- ------- ------------ 1 3 AAA MISSING 4 5 BBB OK 6 7 AAA OK
如果部门只有一组记录,这将是一件简单的事情 - 但是,相同的部门可以显示在不同的范围内,因此使用MIN / MAX执行GROUP BY不起作用,因为它最终会汇总部门AAA的两个范围为一个:
select dept_no, min(item_number), max(item_number), min(status) from inventory group by dept_no START END DEPT_NO STATUS ------ ----- ------- ------------ 1 7 AAA MISSING 4 5 BBB OK
这可以使用数据库视图完成还是太复杂?
答案 0 :(得分:1)
好的,这应该有效
ps:结束和开始是保留字,我无法使用它们。我刚刚添加了一封信,但这仍然是一个明确的结果......
SELECT
i.sstart,
i.eend,
i.dept_no,
MIN(inventory.status) AS status
FROM (
SELECT
DECODE(r, 1, 1, (LAG(max_range_item, 1) OVER(ORDER BY r) + 1) ) AS sstart,
max_range_item AS eend,
dept_no
FROM (
SELECT
rownum AS r,
item_number AS max_range_item,
dept_no
FROM (
SELECT
item_number,
dept_no,
LEAD(dept_no, 1) OVER (ORDER BY item_number) AS next_dept_no
FROM
inventory
ORDER BY
item_number ASC
) i2
WHERE
dept_no != next_dept_no
OR next_dept_no IS NULL
ORDER BY
item_number ASC
) inv
) i
JOIN inventory ON inventory.item_number BETWEEN i.sstart AND i.eend
GROUP BY
i.sstart,
i.eend,
i.dept_no
ORDER BY
i.sstart ASC
答案 1 :(得分:1)
另一种选择(适用于11g)
WITH qry( item_number, dept_no, status, range_id ) as (
select item_number, dept_no, status, 1 range_id
from inventory where item_number = 1
UNION ALL
select src.item_number, src.dept_no, src.status,
case when src.dept_no <> qry.dept_no
then qry.range_id + 1 else qry.range_id
end
from inventory src
join qry on src.item_number = qry.item_number + 1
)
SELECT range_id, dept_no, min(item_number), max(item_number), min(status)
from qry
group by range_id, dept_no
order by 1
;
RANGE_ID DEPT_NO MIN(ITEM_NUMBER) MAX(ITEM_NUMBER) MIN(STATUS)
---------- ------- ---------------- ---------------- -----------
1 AAA 1 3 MISSING
2 BBB 4 5 OK
3 AAA 6 7 OK
答案 2 :(得分:1)
你可以使用窗口函数解决这个问题,但是可以解决这个问题。第一种方法是使用lag()
来确定新“部门”部门的起点。第二个是该值的累积和。累积和作为分组ID,然后可用于聚合。
select dept_no, min(item_number), max(item_number),
(case when sum(case when status = 'MISSING' then 1 else 0 end) > 0
then 'Missing'
else 'Ok'
end)
from (select i.*, sum(GroupStart) over (order by item_number) as Grouping
from (select i.*,
(case when dept_no = lag(dept_no) over (order by item_number)
then 0 else 1
end) as GroupStart
from inventory i
) i
) i
group by dept_no, grouping;
答案 3 :(得分:0)
如果可以使用数据库视图完成此操作,我认为这将非常复杂。您可以研究的一个选项是尝试创建一个内部查询,该查询是在item_number = item_number + 1上连接到自身的同一个表,并添加一个列,用于检测a.item_number!= b.item编号的位置以确定组边界和然后在外部查询中使用此组边界列作为分组。
然而,问题显然更适合于一次循环一行的程序方法。因此,如果可以的话,我建议将其作为pl / sql程序。