从多列中获取最小值和第二最小值的最简单方法是什么(MIN 函数不起作用)?

What is the simplest way to get the least value and second least value from multiple columns (MIN function does not work this)?

以下table来自Teradata数据库

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

我想要的最终结果是,

 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

所以我在网上做了一些研究,他们中的大多数使用带有子查询的 MIN 函数或按分区原始。 Min 函数对我不起作用,因为我有三个独立的列。我想从以上三列中获得最小值或至少两个值。

我尝试使用 Least 函数进行子查询或 CTE,但我无法获得第二小的值。我不确定如何为此使用原始分区。

我们将不胜感激任何与此相关的帮助。

非常感谢!!

你可以这样做:

下面这个:

SELECT MIN(Item_caract)
      FROM (VALUES (Item_length),(Item_width),(Item_heigth)) a(Item_caract)

给你所有列中的最小值

还有这个:

(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))

给你的最小值大于上面的最小值

下面是完整的查询:

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

输出:

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

没有基于集合的解析函数,你的要求很难。我可能会建议取消透视您的数据:

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;

请注意,使用此类逆透视操作的需要可能严重意味着您的 table 应该重新设计为每个项目跨 存储各种测量值,而不是跨列。

如果你真的有三列,你可以简单地应用这个暴力逻辑:

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

对于超过三列,您需要 Tim 的方法,这是一个轻微的变化(如果您的 TD 版本支持 UNPIVOT),避免了回联:

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