Reputation: 41
Below table is from Teradata database
SELECT
sku.Item_id,
sku.Item_length,
sku.Item_width,
sku.Item_heigth,
FROM Category_item sku
Item_id | Item_length | Item_width |Item_heigth
-------------------------------------------
104174 8 6 1
9482763 8 8 8
8434610 8 9 1
2109145 54 34 2
567106 41 41 2
2028731 3 4 3
The final result that I want is,
Item_id | Item_length | Item_width |Item_heigth | MinValue | SecondMinVale
---------------------------------------------------------------------------
104174 8 6 1 1 6
9482763 8 8 8 8 8
8434610 8 9 1 1 8
2109145 54 34 2 2 34
567106 41 41 2 2 41
2028731 3 4 3 3 3
So I did a little research online, most of them used MIN function with a subquery or raw over by partition. Min function does not work for me, because I have three separate columns. I want to get minimum or least two values from the above three columns.
I tried to do subquery or CTE using Least function, but I am stuck with getting the second least value. I am not sure how to use raw over partition for this.
Any help regarding this will be highly appreciated.
Thank you so much!!
Upvotes: 3
Views: 1062
Reputation: 60462
If you actually got three columns you can simply apply this brute-force logic:
SELECT sku.*,
Least(Item_length,Item_width,Item_height) AS MinValue,
CASE
WHEN Item_length BETWEEN Least(Item_width, Item_height) AND
Greatest(Item_width, Item_height)
THEN Item_length
WHEN Item_width BETWEEN Least(Item_length, Item_height) AND
Greatest(Item_length, Item_height)
THEN Item_width
WHEN Item_height BETWEEN Least(Item_width, Item_length) AND
Greatest(Item_width, Item_length)
THEN Item_height
END AS SecondMinValue
FROM Category_item sku
For more than three columns you need Tim's approach, this is a slight variation (if your TD release supports UNPIVOT) avoiding the join-back:
WITH cte AS
(
SELECT up.*
,Row_Number() Over (PARTITION BY item_id ORDER BY val) AS rn
FROM Category_item
UNPIVOT
( val
FOR measure
IN (Item_length AS 'l'
,Item_width AS 'w'
,Item_height AS 'h')
) AS up
)
SELECT
Item_id,
Max(CASE WHEN measure = 'l' THEN val END) AS item_length,
Max(CASE WHEN measure = 'w' THEN val END) AS item_width,
Max(CASE WHEN measure = 'h' THEN val END) AS item_height,
Max(CASE WHEN rn = 1 THEN val END) AS MINVALUE,
Max(CASE WHEN rn = 2 THEN val END) AS SecondMinValue
FROM cte
GROUP BY
Item_id
Upvotes: 1
Reputation: 521073
Without set based analytic functions, your requirement is difficult. I might suggest unpivoting your data:
WITH cte AS (
SELECT Item_id, Item_length AS item FROM Category_item UNION ALL
SELECT Item_id, Item_width FROM Category_item UNION ALL
SELECT Item_id, Item_height FROM Category_item
),
cte2 AS (
SELECT Item_id, item,
ROW_NUMBER() OVER (PARTITION BY Item_id ORDER BY item) rn
FROM cte
)
SELECT
t1.Item_id,
t1.Item_length,
t1.Item_width,
t1.Item_height,
MAX(CASE WHEN rn = 1 THEN t2.item END) AS MinValue,
MAX(CASE WHEN rn = 2 THEN t2.item END) AS SecondMinValue
FROM Category_item t1
INNER JOIN cte2 t2
ON t1.Item_id = t2.Item_id
WHERE
t2.rn <= 2
GROUP BY
t1.Item_id,
t1.Item_length,
t1.Item_width,
t1.Item_height;
Note that the need to use such unpivoting operations might seriously imply that your table should be redesigned with the various measurements being stored per item across rows, rather than across columns.
Upvotes: 1
Reputation: 4061
You can do it this way:
this below:
SELECT MIN(Item_caract)
FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract)
give you the minimum of all columns
and this:
(SELECT MIN(Item_caract)
FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract) where Item_caract >=
(SELECT MIN(Item_caract)
FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract))
gives you the minimum that is bigger than the minimum above
Below is the full query:
select * ,
(SELECT MIN(Item_caract)
FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract))
AS MinValue ,
(SELECT MIN(Item_caract)
FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract) where Item_caract >=
(SELECT MIN(Item_caract)
FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract))
)
AS SecondMinVale
from cte
Output:
104174 8 6 1 1 1
567106 41 41 2 2 2
2028731 3 4 3 3 3
2109145 54 34 2 2 2
8434610 8 9 1 1 1
9482763 8 8 8 8 8
Upvotes: 0