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

时间:2022-05-22 13:02:41

I have 2 tables - 1 with parent records, 1 with child records. For each parent record, I'm trying to return a single child record with the MAX(SalesPriceEach).

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

Additionally I'd like to only return a value when there is more than 1 child record.

另外,当有超过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           |
+-------------------+---------+--------------+

I found a very similar question here, and based my query on the answer but am not seeing the results I expect.

我在这里发现了一个非常相似的问题,基于我的问题的答案,但我没有看到我期望的结果。

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

The results from this query are returning multiple rows for each parent, and not even the highest value first!

这个查询的结果是为每个父元素返回多行,甚至不是最高的值!

4 个解决方案

#1


2  

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)

OR, alternatively:

或者,或者:

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


3  

I know I'm a year late to this party but I always prefer using Row_Number in these situations. It solves the problem when there are two rows that meet your Max criteria and makes sure that only one row is returned:

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

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


0  

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


0  

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

subquery returns table with trans ids and their maximums so just join it with transactions table itself by those 2 values

subquery返回带有trans id和它们的最大值的表因此只需通过这两个值将它与transactions表本身连接起来

#1


2  

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)

OR, alternatively:

或者,或者:

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


3  

I know I'm a year late to this party but I always prefer using Row_Number in these situations. It solves the problem when there are two rows that meet your Max criteria and makes sure that only one row is returned:

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

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


0  

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


0  

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

subquery returns table with trans ids and their maximums so just join it with transactions table itself by those 2 values

subquery返回带有trans id和它们的最大值的表因此只需通过这两个值将它与transactions表本身连接起来