0

I have a SELECT statement that pulls in product information from a related table, and finds the product with the highest quantity associated to it for that transaction. This is shown below and working as expected:

SELECT
qty.[Id], 
qty.[Product_Name],
qty.[Product_Type]

FROM
( SELECT td.[Id], prd.[Product_Name], prd.[Product_Type], 
         ROW_NUMBER() OVER (PARTITION BY prd.Receipt_Number ORDER BY prd.Quantity DESC) AS Row
  FROM [Transactions] td
  INNER JOIN [Products] prd
  ON prd.[Receipt_Number] = td.[Receipt_Number]
  WHERE prd.Quantity > 1 
) qty

WHERE
qty.Row = 1

The issue is that there may be multiple products that have the exact same quantity. Current the system will pull in the first record it finds of the multiple matches, but I would like to exclude this inner query entirely if there is a tie on the highest quantity, returning a null value. Is this possible?

  • Unclear... Assume you have 2 transactions (Receipt_Number), 1 product (P1) with the highest quantity associated with 1st transaction and 2 products (P2, P3) with the same highest quantity associated with 2nd transaction. Your query will return 2 records: P1 and one random from (P2,P3). Where do you want a NULL value to be returned? And the same when the products are P1 and (P1, P2) respectively. – Akina Feb 28 at 5:09
1

It's a bit unclear what you want, but you can use rank() to collect duplicates, and then another window function that counts those, and filter them out if there is more than one:

SELECT qty.Id 
     , qty.Product_Name
     , qty.Product_Type
FROM (
    SELECT qty.Id 
     , qty.Product_Name
     , qty.Product_Type
     , COUNT(Rnk) OVER () as cnt
    FROM ( 
        SELECT td.Id, prd.Product_Name, prd.Product_Type
        ,  RANK() OVER (PARTITION BY prd.Receipt_Number 
                        ORDER BY prd.Quantity) AS Rnk
        FROM Transactions td
        JOIN Products prd
            ON prd.Receipt_Number = td.Receipt_Number
        WHERE prd.Quantity > 1 
    ) qty
    WHERE qty.Rnk = 1
) WHERE cnt = 1;

If you want the rows, but with null instead of values you can use a case expression:

SELECT CASE WHEN cnt = 1 THEN qty.Id END 
     , CASE WHEN ... qty.Product_Name ...
     , ...
FROM (
...
);
  • With COUNT(*) OVER (PARTITION BY Receipt_number, Quanity) , you could have only 1 CTE. – ypercubeᵀᴹ Feb 28 at 12:04
  • 1
    I have 0 now, but I see your point ;-) I'm not entirely sure what the OP wants, so I more or less just copied the original query and adapted it. – Lennart Feb 28 at 12:24
  • I meant 1 level of CTEs or derived table, instead of 2 levels. – ypercubeᵀᴹ Feb 28 at 12:33
0
with qty as
( 
SELECT  td.[Id], 
        prd.[Product_Name], 
        prd.[Product_Type], 
        rank() OVER (PARTITION BY prd.Receipt_Number ORDER BY prd.Quantity DESC) AS rnk
FROM [Transactions] td
     INNER JOIN [Products] prd
        ON prd.[Receipt_Number] = td.[Receipt_Number]
WHERE prd.Quantity > 1 
) 

,cte1 as
(
select *
from qty
where rnk = 1
)


SELECT  [Id], 
        case when max(Product_Name) = min(Product_Name) then max(Product_Name) end as Product_Name,
        case when max(Product_Name) = min(Product_Name) then max(Product_Type) end as Product_Type
FROM  cte1
group by Receipt_Number;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.