SQL从每个父行的子行返回最大值

Posted

技术标签:

【中文标题】SQL从每个父行的子行返回最大值【英文标题】:SQL return max value from child for each parent row 【发布时间】:2011-09-29 13:25:19 【问题描述】:

我有 2 个表 - 1 个带有父记录,1 个带有子记录。对于每个父记录,我试图返回一个带有 MAX(SalesPriceEach) 的子记录。

另外,我只想在有超过 1 个子记录时返回一个值。

parent - SalesTransactions table:
+-------------------+---------+
|SalesTransaction_ID|   text  |
+-------------------+---------+
| 1                 |  Blah   |
| 2                 |  Blah2  |
| 3                 |  Blah3  |
+-------------------+---------+

child - SalesTransactionLines table 
+--+-------------------+---------+--------------+
|id|SalesTransaction_ID|StockCode|SalesPriceEach|
+--+-------------------+---------+--------------+
| 1|   1               |  123    | 99           |
| 2|   1               |   35    | 50           |
| 3|   2               |   15    | 75           |
+--+-------------------+---------+--------------+


 desired results
+-------------------+---------+--------------+
|SalesTransaction_ID|StockCode|SalesPriceEach|
+-------------------+---------+--------------+
|   1               |  123    | 99           |
|   2               |   15    | 75           |
+-------------------+---------+--------------+

我发现了一个非常相似的问题here,并根据答案进行了查询,但没有看到我期望的结果。

WITH max_feature AS (
   SELECT c.StockCode,
          c.SalesTransaction_ID,
          MAX(c.SalesPriceEach)  as feature
     FROM SalesTransactionLines c
 GROUP BY c.StockCode, c.SalesTransaction_ID)
   SELECT p.SalesTransaction_ID,
          mf.StockCode,
          mf.feature
     FROM SalesTransactions p
LEFT JOIN max_feature mf ON mf.SalesTransaction_ID = p.SalesTransaction_ID

此查询的结果为每个父级返回多行,甚至不是首先返回最高值!

【问题讨论】:

【参考方案1】:
select stl.SalesTransaction_ID, stl.StockCode, ss.MaxSalesPriceEach
from SalesTransactionLines stl
inner join 
(
    select stl2.SalesTransaction_ID, max(stl2.SalesPriceEach) MaxSalesPriceEach
    from SalesTransactionLines stl2 
    group by stl2.SalesTransaction_ID
    having count(*) > 1
) ss on (ss.SalesTransaction_ID = stl.SalesTransaction_ID and 
         ss.MaxSalesPriceEach = stl.SalesPriceEach)

或者,或者:

SELECT stl1.*
FROM SalesTransactionLines AS stl1
LEFT OUTER JOIN SalesTransactionLines AS stl2
ON (stl1.SalesTransaction_ID = stl2.SalesTransaction_ID 
    AND stl1.SalesPriceEach < stl2.SalesPriceEach)
WHERE stl2.SalesPriceEach IS NULL;

【讨论】:

【参考方案2】:

我知道我迟到了一年,但我总是更喜欢在这些情况下使用 Row_Number。它解决了当有两行满足您的 Max 条件时的问题,并确保只返回一行:

with z as (
select 
    st.SalesTransaction_ID
    ,row=ROW_NUMBER() OVER(PARTITION BY st.SalesTransaction_ID ORDER BY stl.SalesPriceEach DESC)
    ,stl.StockCode
    ,stl.SalesPriceEach
from 
    SalesTransactions st
    inner join SalesTransactionLines stl on stl.SalesTransaction_ID = st.SalesTransaction_ID
)
select * from z where row = 1   

【讨论】:

这是解决问题的一种非常直接的方法【参考方案3】:
SELECT SalesTransactions.SalesTransaction_ID, 
       SalesTransactionLines.StockCode, 
       MAX(SalesTransactionLines.SalesPriceEach) 
FROM  SalesTransactions RIGHT JOIN SalesTransactionLines 
      ON SalesTransactions.SalesTransaction_ID = SalesTransactionLines.SalesTransaction_ID 
GROUP BY SalesTransactions.SalesTransaction_ID, alesTransactionLines.StockCode;

【讨论】:

【参考方案4】:
select a.SalesTransaction_ID, a.StockCode, a.SalesPriceEach
from SalesTransacions as a 
  inner join (select SalesTransaction_ID, MAX(SalesPriceEach) as SalesPriceEach  
              from SalesTransactionLines group by SalesTransaction_ID) as b
    on a.SalesTransaction_ID = b.SalesTransaction_ID 
       and a.SalesPriceEach = b.SalesPriceEach

子查询返回带有 trans id 及其最大值的表,因此只需通过这 2 个值将其与事务表本身连接起来

【讨论】:

以上是关于SQL从每个父行的子行返回最大值的主要内容,如果未能解决你的问题,请参考以下文章

HTML:如何使用 AngularJs 填充第一行是父行和后续行是子行的行

jquery DataTables 父行和子行作为一条记录而不是两条记录发布到服务器

jQuery tablesorter 仅对子行分组小计

Javascript - 来自具有“父”和“子”行的表中的 Json

带有子行的 T-SQL SELECT 存在优化

选择所有子行都符合条件的父行