Oracle SQL选择最新数据

时间:2018-02-19 12:51:34

标签: sql oracle greatest-n-per-group

早上好,

这是SELECT most recent in Oracle SQL Query

的后续行动

我希望在从这个网站学到很多东西后,将我的Oracle技能提升到一个新的水平。

我在一家小型建筑公司工作,因此,我们从供应商处购买了许多较小的零件/材料。有时,在同一日历年,我们可能会切换我们购买SAME部件的人。我想只为每个PART NUMBER获取最新的VENDOR。这是我的意思的一个例子: 我的起始查询的代码:

WITH

PartNums AS -- Grabs me all of the stuff we "bought", and its vendor, in the construction division since Jan 1 2018
    (
        SELECT 
            PO_ITEM AS "PART_NUM",
            VEND_NUM,
            VEND_NM,
            PODiv AS "DIVISION_CD"
        FROM
                INNER JOIN 
                    (
                        SELECT MAX(PODate) OVER(PARTITION BY PO_Number, VEND_NUM))
                        FROM tblPurchases
                        WHERE PODate > '01-Jan-2017'
                    ) tblTemp INNER JOIN tblPurchases ON tblPurchases.VEND_NUM = tblTemp.VEND_NUM
                INNER JOIN tblVendors ON tblPurchases.VEND_NUM = tblVendors.VEND_NUM
        WHERE
            PODate > '01-Jan-2017'
            AND
            PODiv = 'C'
    ),

Defects AS -- Grabs me the listed defects against their stuff
    (
        SELECT 
            PartNums.*,
            DEFECT_NUM,
            DEFECT_CAT
        FROM
            PartNums
                INNER JOIN tblDefects ON PartNums.PART_NUM = tblDefects.DEFECTIVE_PART_NUM

        WHERE
            DEFECT_DATE > '01-Jan-2017'

    ),

Names AS
    (
        SELECT
            Defects.*,
            PART_NM
        FROM
            Defects
                INNER JOIN tblParts ON Defects.PART_NUM = tblParts.PART_NUM
    )

SELECT
    VEND_NUM,
    VEND_NM,
    PART_NUM,
    PART_NM,
    DEFECT_NUM,
    DEFECT_CAT,
    DIVISION_CD

FROM Names

这会产生以下结果:

| Vendor Number | Vendor Name                  | Part Number | Part Name      | Defect Number | Defect Category | Division | Purchase Order Date |
|---------------|------------------------------|-------------|----------------|---------------|-----------------|----------|---------------------|
| 200123        | Push-Button LLC              | 54211EW     | Faceplate      | PROB333211    | WRPT            | C        | 11-Jan-2017         |
| 200587        | Entirely Concrete            | 69474TR     | 2in Screw      | PROB587412    | WRPT            | C        | 03-Mar-2017         |
| 200444        | Maaco                        | 77489GF     | Hammer NR      | PROB369854    | WRPT            | C        | 08-Aug-2017         |
| 200100        | Fleischman Contractors       | 21110LW     | Service        | PROB215007    | OPYM            | C        | 01-Jun-2017         |
| 200664        | Advanced Tool Repair LLC     | 47219UZ     | Service        | PROB9874579   | UPYM            | C        | 14-Jan-2018         |
| 200999        | AllTech Electronic Equipment | 36654DD     | Plastic Casing | PROB326598    | NA              | C        | 16-Jan-2018         |
| 200321        | ZyotoCard Electronics        | 74200ZN     | Service        | PROB012547    | MISCT           | C        | 19-Apr-2017         |
| 200331        | Black&Decker                 | 41122UT     | .11mm Drillbit | PROB147741    | BRKN            | C        | 03-Aug-2017         |
| 200333        | Sears                        | 41122UT     | .11mm Drillbit | PROB147741    | BRKN            | C        | 11-Mar-2017         |

如您所见,Part Number 41122UT有2个供应商。对于这个部件号,我只想要Black& Decker(其PO日期比Sears新5个月)。

我希望数据看起来像这样:

| Vendor Number | Vendor Name                  | Part Number | Part Name      | Defect Number | Defect Category | Division | Purchase Order Date |
|---------------|------------------------------|-------------|----------------|---------------|-----------------|----------|---------------------|
| 200123        | Push-Button LLC              | 54211EW     | Faceplate      | PROB333211    | WRPT            | C        | 11-Jan-2017         |
| 200587        | Entirely Concrete            | 69474TR     | 2in Screw      | PROB587412    | WRPT            | C        | 03-Mar-2017         |
| 200444        | Maaco                        | 77489GF     | Hammer NR      | PROB369854    | WRPT            | C        | 08-Aug-2017         |
| 200100        | Fleischman Contractors       | 21110LW     | Service        | PROB215007    | OPYM            | C        | 01-Jun-2017         |
| 200664        | Advanced Tool Repair LLC     | 47219UZ     | Service        | PROB9874579   | UPYM            | C        | 14-Jan-2018         |
| 200999        | AllTech Electronic Equipment | 36654DD     | Plastic Casing | PROB326598    | NA              | C        | 16-Jan-2018         |
| 200321        | ZyotoCard Electronics        | 74200ZN     | Service        | PROB012547    | MISCT           | C        | 19-Apr-2017         |
| 200331        | Black&Decker                 | 41122UT     | .11mm Drillbit | PROB147741    | BRKN            | C        | 03-Aug-2017         |

我发现使用MAX()OVER(PARTITION BY)可以用来返回最新的,所以我尝试了这个查询,它现在运行了,但它给了我每个供应商的最新日期,每个部分。不只是每个部分。我需要每个PART的最近的供应商信息(在采购订单上找到,因此最终需要最新的采购订单)。有人可以建议吗?

使用

PartNums AS -- Grabs me all of the stuff we "bought", and its vendor, in the construction division since Jan 1 2018
    (
        SELECT 
            PO_ITEM AS "PART_NUM",
            VEND_NUM,
            VEND_NM,
            PODiv AS "DIVISION_CD"
        FROM
                INNER JOIN 
                    (
                        SELECT PO_NUMBER, VEND_NUM, MAX(PODate) OVER(PARTITION BY PO_NUMBER, VEND_NUM))
                        FROM tblPurchases
                        WHERE PODate > '01-Jan-2017'
                    ) tblTemp INNER JOIN tblPurchases ON tblPurchases.VEND_NUM = tblTemp.VEND_NUM
                INNER JOIN tblVendors ON tblPurchases.VEND_NUM = tblVendors.VEND_NUM
        WHERE
            PODate > '01-Jan-2017'
            AND
            PODiv = 'C'
    ),

Defects AS -- Grabs me the listed defects against their stuff
    (
        SELECT 
            PartNums.*,
            DEFECT_NUM,
            DEFECT_CAT
        FROM
            PartNums
                INNER JOIN tblDefects ON PartNums.PART_NUM = tblDefects.DEFECTIVE_PART_NUM

        WHERE
            DEFECT_DATE > '01-Jan-2017'

    ),

Names AS
    (
        SELECT
            Defects.*,
            PART_NM
        FROM
            Defects
                INNER JOIN tblParts ON Defects.PART_NUM = tblParts.PART_NUM
    )

SELECT
    VEND_NUM,
    VEND_NM,
    PART_NUM,
    PART_NM,
    DEFECT_NUM,
    DEFECT_CAT,
    DIVISION_CD

FROM Names

非常感谢你的时间和帮助。很抱歉,如果这会造成任何歧义。

2 个答案:

答案 0 :(得分:1)

使用DENSE_RANK,RANK或ROW_NUMBER而不是使用MAX,并使用PO_NUMBER,VEND_NUM对其进行分区,按PO_DATE DESC对其进行排序,并过滤掉返回值大于1的记录,

您的查询可能类似于下面,因为您可以看到我使用了DENSE_RANK,

SELECT * 
  FROM (SELECT A.*, DENSE_RANK() OVER(PARTITION BY PO_NUMBER, VEND_NUM ORDER BY podate DESC) rank_value 
          FROM your_table)
  WHERE rank_value = 1;

答案 1 :(得分:0)

据说您正在寻找自特定日期以来报告有缺陷的所有部件,并希望找到相应的订单以便能够与供应商联系。

在Oracle 12c中,您可以使用CROSS APPLY仅加入最新订单(使用ORDER BY date DESC FETCH FIRST ROW ONLY获得)。

select
  o.vend_num as vendor_number,
  o.vend_nm as vendor_name,
  d.defective_part_num as part_number,
  p.part_nm as part_name,
  d.defect_num as defect_number,
  d.defect_cat as defect_category,
  o.podiv as division,
  o.podate as purchase_order_date
from tbldefects d
cross apply
(
  select *
  from tblpurchases pu
  where pu.po_number = d.defective_part_num
    and pu.podate <= d.defect_date
    and pu.podiv = 'C'
  order by pu.podate desc
  fetch first row only
) o
join tblparts p on p.part_num = d.defective_part_num
where d.defect_date >= date '2017-01-01';