kateroh
kateroh

Reputation: 4416

"Partitioned" sorting in a SQL query

The following SQL query that displays products sold sorted by cost and number of orders have to be sorted in a partitioned manner. Namely, products with the cost of under $100 should go first and then everything else that is > $100 should follow it. Adding HAVING TS.TotalSold < 100 to the query would accomplish this for the first partition, but would filter out other products. The operation should be atomic, so that this query can be executed only once.

NOTE: cost by which the query has to be partitioned is calculated as a max of two cost columns, which makes things a bit more complicated (the proposed solutions of CASE WHEN won't work as HighestCost is not a column)


SELECT PS.ProductName, TS.TotalSold, 
  ((PS.Cost1 + PS.Cost2 + ABS(PS.Cost1-PS.Cost2)) / 2) as HighestCost
FROM Products as PS
   CROSS APPLY 
      (SELECT 
         (SELECT COUNT(OrderId) 
          FROM Orders as OS 
          WHERE OS.ProductId=PS.ProductId) 
       as TotalSold) TS
ORDER BY HighestCost ASC, TS.TotalSold

EDIT: modified the query to include calculated cost by which the query has to be partitioned.

Upvotes: 1

Views: 293

Answers (2)

Elroy Flynn
Elroy Flynn

Reputation: 3218

I don't know which dbms you are using but in mine I would use a calculated column to assign a partitionId, and sort by that. Something like this:

SELECT PS.ProductName, TS.TotalSold,
(if cost < 100 then 1 else 2 endif) as partition
FROM Products as PS
   CROSS APPLY 
      (SELECT 
         (SELECT COUNT(OrderId) 
          FROM Orders as OS 
          WHERE OS.ProductId=PS.ProductId) 
       as TotalSold) TS
ORDER BY partition, PS.Cost ASC, TS.TotalSold

Upvotes: 1

RichardTheKiwi
RichardTheKiwi

Reputation: 107716

EDITED

SELECT *
FROM
(
SELECT PS.ProductName, TS.TotalSold, 
  ((PS.Cost1 + PS.Cost2 + ABS(PS.Cost1-PS.Cost2)) / 2) as HighestCost
FROM Products as PS
   CROSS APPLY 
      (SELECT COUNT(OrderId) as TotalSold
       FROM Orders as OS 
       WHERE OS.ProductId=PS.ProductId) TS
) SQ
ORDER BY CASE WHEN HighestCost > 100 THEN 1 END ASC, TotalSold

original below

SELECT PS.ProductName, TS.TotalSold
FROM Products as PS
   CROSS APPLY 
      (SELECT COUNT(OrderId) as TotalSold
       FROM Orders as OS 
       WHERE OS.ProductId=PS.ProductId) TS
ORDER BY
 CASE WHEN TS.TotalSold > 100 THEN 1 END, PS.Cost ASC, TS.TotalSold

You may notice I removed a subquery level since it was extraneous.

Upvotes: 1

Related Questions