SQL - 以前1名返回CTE

时间:2014-08-29 23:24:03

标签: sql greatest-n-per-group

我正在尝试返回一组结果,并决定试试我的运气CTE,第一个表“供应商”,有一个参考列表,第二个表“TVView”,有使用参考创建的票号来自“供应商”表。根据该票证的状态,可能有一张或多张票使用相同的票号,并​​且我想要返回“TVView”中找到的与“供应商”中所选参考匹配的每张票的最后一个条目。此外,“TVView”表具有递增的种子字段。

我得到了这个以返回正确数量的条目(意味着没有显示重复的票证但只显示一次)但是我无法弄清楚如何添加一个额外的图层来回过头来选择该票证的最后一个条目并返回一些其他领域。我可以弄清楚如何总结哪个实际上很容易,但我确实需要“TVView”中每个票据条目的前1个,无论它是否重复,同时从“供应商”返回所有引用。如果SQL支持“Last”

,那会很好

你是怎么做到的?

这是我到目前为止所做的:

with cteTickets as (
    Select s.Mth2, c.Ticket, c.PyRt from Vendor s 
    Inner join 
    TVView c on c.Mth1 = s.Mth1 and c.Vendor = s.Vendor
)
Select Mth2, Ticket, PayRt from cteTickets
Where cteTickets.Vendor >='20'
  and cteTickets.Vendor <='40'
  and cteTickets.Mth2    ='8/15/2014'
Group by cteTickets.Ticket
order by cteTickets.Ticket

1 个答案:

答案 0 :(得分:3)

我所知道的支持Common Table Expressions(CTE)的几个rdbms也支持分析函数,包括非常有用的ROW_NUMBER(),因此以下内容适用于Oracle,TSQL(MSSQL) / Sybase),DB2,PostgreSQL。

在建议中,目的是仅返回TVView中找到的每张票的最新条目。这是通过使用ROW_NUMBER()来完成的,PARTITIONED BY Ticket指示row_number重新开始对Ticket值的每次更改进行编号。随后的ORDER BY Mth1 DESC用于确定每个分区中的哪条记录被分配1,这里它将是最近的日期。

row_number()的输出需要由列别名引用,因此在CTE或派生表中使用它只允许选择RN = 1的最新记录,您将在下面的两个选项中看到这些记录:

- 使用CTE

WITH
      TVLatest
      AS (
            SELECT
                  * -- specify the fields
                , ROW_NUMBER() OVER (PARTITION BY Ticket
                                     ORDER BY Mth1 DESC) AS RN
            FROM TVView
            )
SELECT
      Mth2
    , Ticket
    , PayRt
FROM Vendor v
      INNER JOIN TVLatest l  ON v.Mth1 = l.Mth1
                            AND v.Vendor = l.Vendor
                            AND l.RN = 1
WHERE v.Vendor >= '20'
      AND v <= '40'
      AND v.Mth2 = '2014-08-15'
ORDER BY
      v.Ticket
;

- 改为使用派生表

SELECT
      Mth2
    , Ticket
    , PayRt
FROM Vendor v
      INNER JOIN (
                  SELECT
                        * -- specify the fields
                      , ROW_NUMBER() OVER (PARTITION BY Ticket
                                           ORDER BY Mth1 DESC) AS RN
                  FROM TVView
                 ) TVLatest l  ON v.Mth1 = l.Mth1
                            AND v.Vendor = l.Vendor
                            AND l.RN = 1
WHERE v.Vendor >= '20'
      AND v <= '40'
      AND v.Mth2 = '2014-08-15'
ORDER BY
      v.Ticket
;

请注意:&#34; SELECT *&#34;如果完整的细节未知,则是一种便利或用作缩写。如果没有正确指定字段列表,上述查询可能无法运行(例如,&#39;它们将在Oracle中失败)。