Interview question:How to get last 3 month aggregation at column level?

前端 未结 3 1014
执笔经年
执笔经年 2021-01-16 11:39

This is the question i was being asked at Apple onsite interview and it blew my mind. Data is like this:

orderdate,unit_of_phone_sale

20190806,3000

2019070         


        
相关标签:
3条回答
  • 2021-01-16 12:10

    You can use this query:

    select a.order_month, a.unit_of_phone_sale, 
    LEAD(unit_of_phone_sale, 1, 0) OVER (ORDER BY rownum) AS M_1,
    LEAD(unit_of_phone_sale, 2, 0) OVER (ORDER BY rownum) AS M_2,
    LEAD(unit_of_phone_sale, 3, 0) OVER (ORDER BY rownum) AS M_3
    from (
    select TO_CHAR(orderdate, 'YYYYMM') order_month,
    unit_of_phone_sale,
    rownum
    from Y
    order by order_month desc) a
    

    0 讨论(0)
  • 2021-01-16 12:21

    You will first of all need to sum the month's data and then use the LAG function to get previous months' data as following:

    SELECT
        ORDER_MONTH,
        LAG(UNIT_OF_PHONE_SALE, 1) OVER(
            ORDER BY
                ORDER_MONTH
        ) AS "M-1_Sale",
        LAG(UNIT_OF_PHONE_SALE, 2) OVER(
            ORDER BY
                ORDER_MONTH
        ) AS "M-2_Sale",
        LAG(UNIT_OF_PHONE_SALE, 3) OVER(
            ORDER BY
                ORDER_MONTH
        ) AS "M-3_Sale"
    FROM
        (
            SELECT
                TO_CHAR(ORDERDATE, 'YYYYMM') AS ORDER_MONTH,
                SUM(UNIT_OF_PHONE_SALE) AS UNIT_OF_PHONE_SALE
            FROM
                DATAA
            GROUP BY
                TO_CHAR(ORDERDATE, 'YYYYMM')
        )
    ORDER BY
        ORDER_MONTH DESC;
    

    Output:

    ORDER_   M-1_Sale   M-2_Sale   M-3_Sale
    ------ ---------- ---------- ----------
    201908       3789        789        666
    201907        789        666        765
    201906        666        765
    201905        765
    201904
    

    db<>fiddle demo

    Cheers!!

    -- Update --

    For the requirement mentioned in the comments, Following query will work for it.

    CTE AS (
        SELECT
            TRUNC(ORDERDATE, 'MONTH') AS ORDER_MONTH,
            SUM(UNIT_OF_PHONE_SALE) AS UNIT_OF_PHONE_SALE
        FROM
            DATAA
        GROUP BY
            TRUNC(ORDERDATE, 'MONTH')
    )
    
    SELECT
        TO_CHAR(C.ORDER_MONTH,'YYYYMM') as ORDER_MONTH,
        NVL(C1.UNIT_OF_PHONE_SALE, 0) AS "M-1_Sale",
        NVL(C2.UNIT_OF_PHONE_SALE, 0) AS "M-2_Sale",
        NVL(C3.UNIT_OF_PHONE_SALE, 0) AS "M-3_Sale"
    FROM
        CTE C
        LEFT JOIN CTE C1 ON ( C1.ORDER_MONTH = ADD_MONTHS(C.ORDER_MONTH, - 1) )
        LEFT JOIN CTE C2 ON ( C2.ORDER_MONTH = ADD_MONTHS(C.ORDER_MONTH, - 2) )
        LEFT JOIN CTE C3 ON ( C3.ORDER_MONTH = ADD_MONTHS(C.ORDER_MONTH, - 3) )
    ORDER BY
        C.ORDER_MONTH DESC
    

    Output:

    db<>fiddle demo of updated answer.

    Cheers!!

    0 讨论(0)
  • 2021-01-16 12:23

    I think LEAD function can help here -

    SELECT TO_CHAR(orderdate, 'YYYYMM') "DATE"
      ,unit_of_phone_sale M_1_Sale
      ,LEAD(unit_of_phone_sale,1,0) OVER(ORDER BY TO_CHAR(orderdate, 'YYYYMM') DESC) M_2_Sale
      ,LEAD(unit_of_phone_sale,2,0) OVER(ORDER BY TO_CHAR(orderdate, 'YYYYMM') DESC) M_3_Sale
      ,LEAD(unit_of_phone_sale,3,0) OVER(ORDER BY TO_CHAR(orderdate, 'YYYYMM') DESC) M_4_Sale
    FROM table_sales
    

    Here is the DB Fiddle

    0 讨论(0)
提交回复
热议问题