+------------+---------------+---------------+----------------+
| Product ID | Part Sequence | Part Material | Description |
+------------+---------------+---------------+----------------+
| 1 | 1 | Steel | Part A |
| 1 | 2 | CFK | Part B |
| 1 | 3 | CFK | Part B Variant |
| 1 | 4 | Steel | Part C |
| 1 | 5 | GFK | Part D |
| 1 | 6 | Plastic | Part E |
| 2 | 1 | Steel | Part A |
| 2 | 2 | CFK | Part B |
| 2 | 3 | Steel | Part F |
| 2 | 4 | CFK | Part B |
| 2 | 5 | Steel | Part G |
| 2 | 6 | Silicon | Part D+ |
| 2 | 7 | Plastic | Part E |
+------------+---------------+---------------+----------------+
(按产品ID和部件顺序排序只是为了便于阅读,我的数据库表是无序的)
我需要查询每个产品ID的所有行,其零件序列等于或高于最后一个钢件。
因此,对于上表,预期结果将是:
+------------+---------------+---------------+----------------+
| Product ID | Part Sequence | Part Material | Description |
+------------+---------------+---------------+----------------+
| 1 | 4 | Steel | Part C |
| 1 | 5 | GFK | Part D |
| 1 | 6 | Plastic | Part E |
| 2 | 5 | Steel | Part G |
| 2 | 6 | Silicon | Part D+ |
| 2 | 7 | Plastic | Part E |
+------------+---------------+---------------+----------------+
我可以使用SQL Select only rows with Max Value on a Column FILTERED by Column中的解决方案找到最后一个钢件,然后过滤任何具有更高零件序列的零件,但我希望能提供更有效的解决方案。
答案 0 :(得分:4)
使用窗口化聚合函数(只需要对表进行一次传递)而不是使用连接(需要两次遍历表):
[它还将返回没有钢件的产品 - 如果这是一个问题,那么可以使用类似的窗口查询来过滤掉这些行。]
Oracle 11g R2架构设置:
CREATE TABLE TEST ( Product_ID, Part_Sequence, Part_Material, Description ) AS
SELECT 1, 1, 'Steel', 'Part A' FROM DUAL
UNION ALL SELECT 1, 2, 'CFK', 'Part B' FROM DUAL
UNION ALL SELECT 1, 3, 'CFK', 'Part B Variant' FROM DUAL
UNION ALL SELECT 1, 4, 'Steel', 'Part C' FROM DUAL
UNION ALL SELECT 1, 5, 'GFK', 'Part D' FROM DUAL
UNION ALL SELECT 1, 6, 'Plastic', 'Part E' FROM DUAL
UNION ALL SELECT 2, 1, 'Steel', 'Part A' FROM DUAL
UNION ALL SELECT 2, 2, 'CFK', 'Part B' FROM DUAL
UNION ALL SELECT 2, 3, 'Steel', 'Part F' FROM DUAL
UNION ALL SELECT 2, 4, 'CFK', 'Part B' FROM DUAL
UNION ALL SELECT 2, 5, 'Steel', 'Part G' FROM DUAL
UNION ALL SELECT 2, 6, 'Silicon', 'Part D+' FROM DUAL
UNION ALL SELECT 2, 7, 'Plastic', 'Part E' FROM DUAL
UNION ALL SELECT 3, 1, 'Silicon', 'Part A' FROM DUAL
UNION ALL SELECT 3, 2, 'Plastic', 'Part B' FROM DUAL;
查询1 :
SELECT Product_ID,
Part_Sequence,
Part_Material,
Description
FROM (
SELECT t.*,
COALESCE(
SUM( CASE Part_Material WHEN 'Steel' THEN 1 ELSE 0 END )
OVER ( PARTITION BY Product_ID
ORDER BY Part_Sequence
ROWS BETWEEN 1 FOLLOWING AND UNBOUNDED FOLLOWING ),
0
) AS isInvalid
FROM TEST t
)
WHERE isInvalid = 0
<强> Results 强>:
| PRODUCT_ID | PART_SEQUENCE | PART_MATERIAL | DESCRIPTION |
|------------|---------------|---------------|-------------|
| 1 | 4 | Steel | Part C |
| 1 | 5 | GFK | Part D |
| 1 | 6 | Plastic | Part E |
| 2 | 5 | Steel | Part G |
| 2 | 6 | Silicon | Part D+ |
| 2 | 7 | Plastic | Part E |
| 3 | 1 | Silicon | Part A |
| 3 | 2 | Plastic | Part B |
答案 1 :(得分:2)
尝试以下
Select * from product
join
(Select Max(Part_Sequence) as sequence,productid from product
group by Productid, Part Sequence) d
on product.Part_Sequence = d.sequence
and product.productid = d.productid
如果要查询特定部分,只需将where子句应用于该部分的内部和外部查询
答案 2 :(得分:1)
试试这个
select t1.* from table as t1 inner join
(
select product_id,max(Part_Sequence) as Part_Sequence from table as t
where Part_Material='Steel'
group by product_id
) t2 on t1.product_id=t2.product_id
where t1.Part_Sequence>=t2.Part_Sequence
答案 3 :(得分:1)
如果不同String.fromCString(buf)
的数量与表中的行数相比较低,那么使用连接可能表现良好(否则具有窗口函数的解决方案会更快):
product_id
请注意,这不会返回没有select p.*
from parts p
join (
select product_id, max(part_sequence) as max_seq
from parts
where part_material = 'Steel'
group by product_id
) t on t.product_id = p.product_id and p.part_sequence >= t.max_seq
行的部分。我不知道这是否是一种可能的情况。