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

时间:2020-01-30 15:32:58

标签: sql tsql pivot pivot-table histogram

假设我的表格中有几列(实际上是107列):COLUMN_A,COLUMN_B,COLUMN_C,COLUMN_D等...

我想从每一个中提取信息,例如最小/最大长度,空/空数量和最小/最大值。

要单独分析每一列,我使用以下代码:

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)

我可以手动更改第一行的变量,以便“有效地”更改目标列。

我还知道,访问INFORMATION_SCHEMA可以使用以下脚本轻松获得一个表格,其中每一列都为一行:

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

但是我不知道如何使#TEMP_COLS表的每一行都运行第一个查询... 我觉得我需要数据透视表,但是我不知道从哪里开始。我肯定不能整体旋转MY_TABLE,因为它有大约一百万行...即使如此,我认为旋转也是要走的路。而且由于语法我对此有点害怕。

如果您知道其他方法,请分享。如果您知道如何解决该问题,请教我,大声笑。

谢谢。

2 个答案:

答案 0 :(得分:0)

您可以循环访问临时表中的行,并将结果存储在另一个临时表中。

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'

您的代码,但带有指示符已处理,可在计算列时进行注册。

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

#MinMaxValues的临时表声明。该表将在我们遍历每个#TEMP_COLS记录时存储每一列的结果。

迭代可能是一个游标,但是由于游标非常慢,因此我更喜欢在#TEMP_COLS的每个记录中进行迭代,而我们的指标 isProcessed 为0,这意味着 @col 将收到一个值。当前行的每个已处理记录更新 isProcessed 都为1。

答案 1 :(得分:0)

您正在寻找的是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

取消验证码

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 ;