【问题标题】:How to get min(date), max(date) and its quantity from the same table?如何从同一张表中获取 min(date)、max(date) 及其数量?
【发布时间】:2019-11-05 18:23:58
【问题描述】:

我是这个 sql 编码的新手,我正在尝试学习新的东西。因此,我创建了一个包含一些属性的交货表,如项目代码、交货日期、交货数量。所以 如何从同一张表中获取第一个交货日期(最小日期)和交货数量以及最迟交货日期(最大日期)及其交货数量?

我尝试使用 union 子句来获取 min(日期)和 max(日期)及其数量。但是输出的显示并不像我想象的那样

这是我尝试过的

SELECT item_code , MAX(date) AS "Latest_delivery_date", quantity
FROM delivery
WHERE item_code='110192'
GROUP BY item_code
union all
SELECT item_code , MIN(date) AS "First_delivery_date", quantity
FROM delivery 
WHERE item_code='110192'
GROUP BY item_code;

我希望输出看起来像

【问题讨论】:

    标签: mysql sql database oracle


    【解决方案1】:

    解决此问题的一种方法是创建一个包含 MINMAX 交货日期的派生表,然后将 JOIN 返回表中以查找这些日期的数量。例如:

    SELECT m.item_code, 
           m.min_date AS "First_delivery_date",  d1.quantity AS "First_quantity",
           m.max_date AS "Latest_delivery_date", d2.quantity AS "Latest_quantity"
    FROM (SELECT item_code, MAX(date) AS max_date, MIN(date) AS min_date
          FROM delivery
          GROUP BY item_code) m
    JOIN delivery d1 ON d1.item_code = m.item_code AND d1.date = m.min_date
    JOIN delivery d2 ON d2.item_code = m.item_code AND d2.date = m.max_date
    

    Demo on dbfiddle

    要为一个特定的item_code 选择结果,请将WHERE 子句添加到派生表中。这会将该表的结果限制为仅针对该 item_code 的行,从而使后续的 JOINs 更有效率。例如:

    SELECT m.item_code, 
           m.min_date AS "First_delivery_date",  d1.quantity AS "First_quantity",
           m.max_date AS "Latest_delivery_date", d2.quantity AS "Latest_quantity"
    FROM (SELECT item_code, MAX(date) AS max_date, MIN(date) AS min_date
          FROM delivery
          WHERE item_code = '010997'
          GROUP BY item_code) m
    JOIN delivery d1 ON d1.item_code = m.item_code AND d1.date = m.min_date
    JOIN delivery d2 ON d2.item_code = m.item_code AND d2.date = m.max_date
    

    【讨论】:

    • 如果商品很多,我想过滤商品代码怎么办?我应该把 item_code ='010997' 放在哪里?
    • @newbeginnner 将WHERE item_code = '010997' 放入派生表中是最有效的。这会将结果从该表减少到 1 行,从而使后续的 JOIN 更快。
    • 我试过了,效果很好。代码更容易理解。谢谢你的帮助,先生
    • @newbeginnner 很遗憾,您不能接受两个答案!我很高兴你有一个可行的解决方案。
    • @newbeginnner 只需将其添加到派生表中。看这个演示dbfiddle.uk/…
    【解决方案2】:

    您可以使用analytical functions,如下:

    SQL> CREATE TABLE DELIVERY (
      2      ITEM_CODE   NUMBER,
      3      DATE_       DATE,
      4      QUANTITY    NUMBER
      5  );
    
    Table created.
    
    SQL>
    SQL> INSERT INTO DELIVERY VALUES (
      2      110192,
      3      DATE '2019-05-05',
      4      30
      5  );
    
    1 row created.
    
    SQL>
    SQL> INSERT INTO DELIVERY VALUES (
      2      110192,
      3      DATE '2019-01-01',
      4      10
      5  );
    
    1 row created.
    
    SQL>
    SQL> INSERT INTO DELIVERY VALUES (
      2      110192,
      3      DATE '2019-10-10',
      4      25
      5  );
    
    1 row created.
    
    SQL>
    SQL> INSERT INTO DELIVERY VALUES (
      2      110192,
      3      DATE '2019-08-08',
      4      19
      5  );
    
    1 row created.
    
    SQL>
    SQL> SELECT DISTINCT
      2      ITEM_CODE,
      3      MIN(DATE_) OVER(
      4          PARTITION BY ITEM_CODE
      5      ) AS FIRST_DELIVERY_DATE,
      6      MAX(QUANTITY) KEEP(DENSE_RANK FIRST ORDER BY DATE_) OVER(
      7          PARTITION BY ITEM_CODE
      8      ) AS FIRST_QUANTITY,
      9      MAX(DATE_) OVER(
     10          PARTITION BY ITEM_CODE
     11      ) AS LATEST_DELIVERY_DATE,
     12      MAX(QUANTITY) KEEP(DENSE_RANK FIRST ORDER BY DATE_ DESC NULLS LAST) OVER(
     13          PARTITION BY ITEM_CODE
     14      ) AS LATEST_QUANTITY
     15  FROM
     16      DELIVERY;
    
     ITEM_CODE FIRST_DEL FIRST_QUANTITY LATEST_DE LATEST_QUANTITY
    ---------- --------- -------------- --------- ---------------
        110192 01-JAN-19             10 10-OCT-19              25
    
    SQL>
    

    干杯!!

    【讨论】:

    • 这行得通!由于我是这个 sql 编码的新手,我不知道 Over Partition By 子句。谢谢你给我展示了一些新东西。
    猜你喜欢
    • 2020-06-18
    • 2022-07-16
    • 2019-06-25
    • 1970-01-01
    • 2017-03-03
    • 2020-11-01
    • 1970-01-01
    • 2019-08-30
    • 2022-08-02
    相关资源
    最近更新 更多