【问题标题】:SQL Query to get 2nd most recent results with multiple columnsSQL 查询以获取具有多列的第二个最新结果
【发布时间】:2020-09-16 08:23:48
【问题描述】:

我正在尝试获取所有不同 part_id(基于 order_date)的第二个最新结果,以进入我正在制作的报告中,以将其与最新结果进行比较。

评论部分来自我尝试但未成功的另一种方法。

非常感谢任何帮助!

(旁注:我是在 SO 上发帖的新手,如果在其他地方得到回答,我提前道歉,但我找不到与此问题相关的任何内容)

我正在使用以下查询:

SELECT
                              PURCHASE_ORDER.ORDER_DATE
                            , PURC_ORDER_LINE.PART_ID
                            , PURCHASE_ORDER.VENDOR_ID
                            , PURC_ORDER_LINE.LINE_STATUS
                            , PURC_ORDER_LINE.ORDER_QTY
                            , PURC_ORDER_LINE.UNIT_PRICE
                            --, ROW_NUMBER() over (ORDER BY PURCHASE_ORDER.ORDER_DATE DESC)AS ROW
                            , CAST (PURC_ORDER_LINE.ORDER_QTY * PURC_ORDER_LINE.UNIT_PRICE AS VARCHAR) AS TOTAL_COST
                    FROM
                              PURCHASE_ORDER
                              INNER JOIN
                                        PURC_ORDER_LINE
                              ON
                                        PURCHASE_ORDER.ID = PURC_ORDER_LINE.PURC_ORDER_ID

                    WHERE PURCHASE_ORDER.ORDER_DATE < (SELECT MAX(ORDER_DATE) FROM PURCHASE_ORDER) AND PURC_ORDER_LINE.PART_ID = 'XXXX'
                    ORDER BY ORDER_dATE DESC





                    --WHERE PURC_ORDER_LINE.PART_ID = 'XXXX' and PURCHASE_ORDER.ORDER_DATE = (SELECT MAX(ORDER_DATE) FROM PURCHASE_ORDER WHERE ORDER_DATE < (SELECT MAX(ORDER_DATE) FROM PURCHASE_ORDER))

编辑 5/28 深夜:

下面是我需要每个 part_id 的第二个结果的数据集(第二个基于 ORDER_DATE DESC)

+-------------+---------+-----------+
| ORDER_DATE  | PART_ID | VENDOR_ID |
+-------------+---------+-----------+
| 2020-05-29  | XXXX    | CVVB      |
| 2020-05-27  | XXXX    | CVVB      |
| 2020-05-28  | XXXX    | CVVA      |
| 2020-05-28  | YYYY    | GGNB      |
| 2020-04-12  | YYYY    | GGNB      |
| 2020-02-08  | YYYY    | GGNB      |
| 2020-05-28  | ZZZZ    | LLNB      |
| 2019-10-28  | ZZZZ    | LLNB      |
| 2019-05-27  | ZZZZ    | OKIJ      |
+-------------+---------+-----------+

我希望收到以下输出(超过 3 个不同的零件 ID):

+------------+---------+-----------+
| ORDER_DATE | PART_ID | VENDOR_ID |
+------------+---------+-----------+
| 2020-05-28 | XXXX    | CVVA      |
| 2020-04-12 | YYYY    | GGNB      |
| 2019-10-28 | ZZZZ    | LLNB      |
+------------+---------+-----------+

查询中还有其他列,但将它们格式化为表格会花费更长的时间。我已经省略了示例中的一些列。

另一个编辑

我不确定这些信息是否有帮助,但我正在尝试将最近的结果与之前的结果进行比较,以显示定价和供应商的差异。我们正在将数据编译到报表生成器中;我在这里的方法是创建 2 个单独的数据集,一个是最新的,另一个是第二个最新的,然后在 Report Builder 中合并来自数据集的数据。如果有更简单的方法并且我走错了方向,请告诉我!

例子:

+------------+---------+-----------+-------------+----------+------------+
| ORDER_DATE | PART_ID | VENDOR_ID | Porder_Date | Ppart_ID | pVendor_id |
+------------+---------+-----------+-------------+----------+------------+
| 2020-05-29 | XXXX    | CVVB      | 2020-05-28  | XXXX     | CVVA       |
| 2020-05-28 | YYYY    | GGNB      | 2020-04-12  | YYYY     | GGNB       |
| 2020-05-28 | ZZZZ    | LLNB      | 2019-10-28  | ZZZZ     | LLNB       |
+------------+---------+-----------+-------------+----------+------------+

编辑第二天早上

感谢大家的帮助!在 Harry 发布了他的解决方案后,我继续进行了一些微小的编辑以添加我需要的列。我用原来的 select 语句交换了他的 union 部分。这里的一切似乎正是我正在寻找的!

代码:

;
WITH mycte AS
          (
                    SELECT
                              PURCHASE_ORDER.ORDER_DATE
                            , PURC_ORDER_LINE.PART_ID
                            , PURCHASE_ORDER.VENDOR_ID
                            , PURC_ORDER_LINE.LINE_STATUS
                            , PURC_ORDER_LINE.ORDER_QTY
                            , PURC_ORDER_LINE.UNIT_PRICE
                            , CAST (PURC_ORDER_LINE.ORDER_QTY * PURC_ORDER_LINE.UNIT_PRICE AS VARCHAR) AS TOTAL_COST
                    FROM
                              PURCHASE_ORDER
                              INNER JOIN
                                        PURC_ORDER_LINE
                              ON
                                        PURCHASE_ORDER.ID = PURC_ORDER_LINE.PURC_ORDER_ID
          )
        , mycte2 AS
          (
                    SELECT
                              CONVERT(DATE,order_date) AS order_date
                            , part_id
                            , vendor_id
                            , order_qty
                            , unit_price
                            , total_cost
                            , ROW_NUMBER() over(
                                      PARTITION BY part_id
                                      ORDER BY
                                                CONVERT(DATE,order_date) DESC) AS row_num
                    FROM
                              mycte
          )
SELECT
          mycte2.order_date
        , mycte2.part_id
        , mycte2.vendor_id
        , mycte2.order_qty
        , mycte2.unit_price
        , mycte2.total_cost
        , previous.order_date porder_date
        , previous.part_id    ppart_id
        , previous.vendor_id  pvendor_id
        , previous.order_qty  poqrder_qty
        , previous.unit_price punit_price
        , previous.total_cost ptotal_cost
FROM
          mycte2
          LEFT JOIN
                    mycte2 previous
          ON
                    previous.row_num   = mycte2.row_num +1
                    AND mycte2.part_id = previous.part_id
WHERE
          mycte2.row_num = 1

【问题讨论】:

  • 您可以只选择前 2 条记录并按 ORDER_DATE desc 排序。我错过了什么吗?
  • 抱歉 - 我需要每个唯一 part_id 的前 2 个结果
  • 我会研究 OUTER 和 CROSS 是否适用。我需要两个表结构来编写正确的查询。基本上你想先从LINE表中选择,然后是相应的订单。
  • 我不认为我遵循 - LINE 表是什么意思? PURC_ORDER_LINE?表的 P​​K 用于连接在一起。
  • @tsallad 您能否展示一些示例数据和所需的输出?请编辑问题以显示这些

标签: sql reporting-services


【解决方案1】:

我认为这样的事情可以得到第二个最近的订单:

;WITH cteOrders AS (
 SELECT ROW_NUMBER() OVER (ORDER BY Order_Date DESC) AS row_num,
    PURCHASE_ORDER.ORDER_DATE
    , PURC_ORDER_LINE.PART_ID
    , PURCHASE_ORDER.VENDOR_ID
    , PURC_ORDER_LINE.LINE_STATUS
    , PURC_ORDER_LINE.ORDER_QTY
    , PURC_ORDER_LINE.UNIT_PRICE
 FROM PURCHASE_ORDER 
 INNER JOIN PURC_ORDER_LINE ON PURCHASE_ORDER.ID = PURC_ORDER_LINE.PURC_ORDER_ID
 WHERE PURCHASE_ORDER.ORDER_DATE < (SELECT MAX(ORDER_DATE) FROM PURCHASE_ORDER) AND PURC_ORDER_LINE.PART_ID = 'XXXX'
 )
 SELECT * FROM cteOrders WHERE row_num = 2

【讨论】:

  • 嘿桑迪亚!非常感谢您的回复,正如 briskovich 指出的那样,我的原始帖子中缺少这部分 - 但我希望返回表中所有不同零件编号的前 2 个(或第 2 个结果)。
  • 在这种情况下,您只需将上述 select 中的 where 子句更改为 where row_num
  • 谢谢哈利!不过,这只是返回 2 个结果,因为我们有超过 1000 个 part_id,我需要它来返回表中所有 part_id 的 2 个结果(或仅返回第 2 个结果)。
【解决方案2】:

根据您提供的数据,您可以使用 cte 和行号函数来执行此操作。

注意 - 它总是有助于展示整个画面,而不是仅仅要求您需要帮助的部分(通常).. 因为如果我们能够理解整个问题,回答起来会更容易!

见下方代码

;with mycte as (


select 
 '2020-05-29' as order_date  , 'XXXX'  as part_id   , 'CVVB' as vendor_id
 union all select
 '2020-05-27'  , 'XXXX'    , 'CVVB'  
  union all select
 '2020-05-28'  , 'XXXX'    , 'CVVA'      
  union all select
 '2020-05-28'  , 'YYYY'    , 'GGNB'     
  union all select
 '2020-04-12'  , 'YYYY'    , 'GGNB'      
  union all select
 '2020-02-08'  , 'YYYY'    , 'GGNB'     
  union all select
 '2020-05-28'  , 'ZZZZ'    , 'LLNB'      
  union all select
 '2019-10-28' , 'ZZZZ'    , 'LLNB'    
  union all select
 '2019-05-27'  , 'ZZZZ'    , 'OKIJ' 
 )
 , mycte2 as (
 Select 
  convert(date,order_date) as order_date
 ,part_id
 ,vendor_id
 ,ROW_NUMBER() over( partition by part_id order by convert(date,order_date) desc) as row_num
 from mycte
)

Select 
mycte2.order_date
,mycte2.part_id
,mycte2.vendor_id
,previous.order_date porder_date
,previous.part_id ppart_id
,previous.vendor_id pvendor_id
from  mycte2

 left join mycte2 previous
    on previous.row_num = mycte2.row_num +1
    and mycte2.part_id = previous.part_id

where mycte2.row_num = 1

结果

【讨论】:

  • 嘿@Harry 这看起来很棒!不过,我确实有一个问题 - 对于我想从中获得第二行返回的每个零件号,我是否必须在每个 Part_ID 的联合部分中添加特定信息?
  • 更新 - 我看到我似乎可以用我的帖子中的原始查询替换联合部分(减去 orderby)并获得我正在寻找的结果。我添加了完成报告所需的其他列,看来我不必使用您的解决方案从报告构建中的 2 个数据集编译它!太感谢了!!!我已将最终查询更新为顶部的问题!!!
猜你喜欢
  • 2013-03-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 2022-09-28
  • 2021-01-11
  • 2018-10-12
  • 2014-12-02
  • 1970-01-01
相关资源
最近更新 更多