简体   繁体   English

SQL - 为每列选择最小值和最大值

[英]SQL - Select min and max value for each column

Supose I have a table with a few (actually 107) columns: COLUMN_A, COLUMN_B, COLUMN_C, COLUMN_D, etc...假设我有一个包含几列(实际上是 107 列)的表:COLUMN_A、COLUMN_B、COLUMN_C、COLUMN_D 等...

Out of each of them i want to extract informations such as minimum/maximum length, null+empty quantity and minimum/maximum value.在他们每个人中,我想提取诸如最小/最大长度、空+空数量和最小/最大值之类的信息。

To analyze each column individually i use the following code:要单独分析每一列,我使用以下代码:

DECLARE @col VARCHAR(max) =   'COLUMN_A'

DECLARE @RUN_QUERY AS VARCHAR(MAX)
SET @RUN_QUERY = 'SELECT MIN(LEN(' + @col + ')) AS CHR_MIN, MAX(LEN(' + @col + ')) AS CHR_MAX, MIN(' + @col + ') AS VALUE_MIN, MAX(' + @col + ') AS VALUE_MAX FROM MY_TABLE'
EXEC(@RUN_QUERY)

and manually i can change the variable on first line in order to "efficiently" change targeted column.我可以手动更改第一行的变量,以便“有效”更改目标列。

I also know that accessing the INFORMATION_SCHEMA i can easily get a table with every column as a row with following script:我也知道访问 INFORMATION_SCHEMA 我可以很容易地得到一个表,每一列都是一行,下面的脚本:

SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION
INTO #TEMP_COLS
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = MY_TABLE
ORDER BY 3

But i dont know how to make the first query run for every line of the #TEMP_COLS table... I feel i need a pivot table, but i don't know where to start.但我不知道如何为 #TEMP_COLS 表的每一行运行第一个查询......我觉得我需要一个数据透视表,但我不知道从哪里开始。 I surely can't pivot MY_TABLE as a whole because it has about half a million lines... even so, i think pivotting is the way to go.我当然不能将 MY_TABLE 作为一个整体旋转,因为它有大约 50 万行……即便如此,我认为旋转是要走的路。 And i am a little bit scared of it because of the syntax.由于语法,我有点害怕它。

If you know any other way around please share it.如果您知道任何其他方式,请分享。 If you know how to pivot the solution away please teach me, lol.如果你知道如何解决这个问题,请教我,哈哈。

Thanks in advance.提前致谢。

You can loop the rows of your temporary table and store results in another temporary table.您可以循环临时表的行并将结果存储在另一个临时表中。

IF OBJECT_ID('tempdb..#TEMP_COLS') IS NOT NULL
    DROP TABLE #TEMP_COLS
SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, CAST(0 as BIT) as isProcessed
INTO #TEMP_COLS
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'YourTable'

Your code but with an indicator isProcessed to register when the column has been calculated.您的代码但带有指示器isProcessed以在计算列时进行注册。

DECLARE @RUN_QUERY AS VARCHAR(MAX)
DECLARE @col VARCHAR(max) =  (SELECT TOP 1 COLUMN_NAME FROM #TEMP_COLS WHERE isProcessed = 0)

IF OBJECT_ID('tempdb..#MinMaxValues') IS NOT NULL
    DROP TABLE #MinMaxValues
CREATE TABLE #MinMaxValues (
    COLUMN_NAME VARCHAR(max),
    CHR_MIN int,
    CHR_MAX int,
    VALUE_MIN VARCHAR(max),
    VALUE_MAX VARCHAR(max),
)

WHILE @col IS NOT NULL
BEGIN

    SET @RUN_QUERY = '
    INSERT INTO #MinMaxValues
    SELECT  ''' + @col + ''',
            MIN(LEN(' + @col + ')) AS CHR_MIN, 
            MAX(LEN(' + @col + ')) AS CHR_MAX, 
            MIN(' + @col + ') AS VALUE_MIN, 
            MAX(' + @col + ') AS VALUE_MAX 
            FROM YourTable
    GROUP BY ' + @col
    EXEC(@RUN_QUERY)

    UPDATE #TEMP_COLS SET isProcessed = 1 WHERE COLUMN_NAME = @col
    SET @col = null
    SELECT TOP 1 @col = COLUMN_NAME FROM #TEMP_COLS WHERE isProcessed = 0
END


SELECT * from #MinMaxValues

Temporary table declaration for #MinMaxValues. #MinMaxValues 的临时表声明。 This table will store the results for each column while we iterate through each #TEMP_COLS record.当我们遍历每个#TEMP_COLS 记录时,该表将存储每一列的结果。

The iteration could be a cursor, but since cursors are very slow, I prefer to iterate through each record in #TEMP_COLS while our indicator isProcessed is 0, meaning @col will receive a value.迭代可能是一个游标,但由于游标非常慢,我更喜欢迭代#TEMP_COLS 中的每条记录,而我们的指标isProcessed为 0,这意味着@col将收到一个值。 Each processed record update isProcessed of the current row with the value of 1.每个处理过的记录更新都是对值为 1 的当前行进行处理。

What you are looking for is an UNPIVOT.您正在寻找的是 UNPIVOT。 unpivot-example 逆透视示例

DROP TABLE IF EXISTS yourTable; 

CREATE TABLE yourTable (
    COL_01 INT NULL
  , COL_02 INT NULL
  , COL_03 INT NULL
  , COL_04 INT NULL
  , COL_05 INT NULL
  , COL_06 INT NULL
  , COL_07 INT NULL
  , COL_08 INT NULL
  , COL_09 INT NULL
  , COL_10 INT NULL
  , COL_11 INT NULL
  , COL_12 INT NULL
  , COL_13 INT NULL
  , COL_14 INT NULL
  , COL_15 INT NULL
) ;
GO

INSERT INTO dbo.yourTable (COL_01
                           , COL_02
                           , COL_03
                           , COL_04
                           , COL_05
                           , COL_06
                           , COL_07
                           , COL_08
                           , COL_09
                           , COL_10
                           , COL_11
                           , COL_12
                           , COL_13
                           , COL_14
                           , COL_15
)
VALUES (
   CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
  ,CAST ((RAND()*100) AS INT)
) ;
GO 20

SELECT TOP (100) * FROM dbo.yourTable

Unpivot Code逆透视代码

SELECT
    unpvt.ColumnName
  , MAX( ColumnValue )
  , MIN( ColumnValue )
  , AVG( ColumnValue )
FROM (
    SELECT
        COL_01
      , COL_02
      , COL_03
      , COL_04
      , COL_05
      , COL_06
      , COL_07
      , COL_08
      , COL_09
      , COL_10
      , COL_11
      , COL_12
      , COL_13
      , COL_14
      , COL_15
    FROM dbo.yourTable
) p
    UNPIVOT (
        ColumnValue
        FOR ColumnName IN (COL_01, COL_02, COL_03, COL_04, COL_05, COL_06, COL_07, COL_08, COL_09, COL_10, COL_11
                           , COL_12, COL_13, COL_14, COL_15
        )
    ) AS unpvt
GROUP BY unpvt.ColumnName ;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM