SQL - Выберите минимальное и максимальное значение для каждого столбца - PullRequest
0 голосов
/ 30 января 2020

Предположим, у меня есть таблица с несколькими (на самом деле 107) столбцами: COLUMN_A, COLUMN_B, COLUMN_ C, COLUMN_D и др. c ...

Из каждого из них я хочу извлечь информация, такая как минимальная / максимальная длина, ноль + пустое количество и минимальное / максимальное значение.

Для индивидуального анализа каждого столбца я использую следующий код:

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 в целом, потому что в нем около полумиллиона строк ... даже в этом случае, я думаю, что поворот - это путь к go. И я немного боюсь этого из-за синтаксиса.

Если вы знаете какой-либо другой способ, пожалуйста, поделитесь им. Если вы знаете, как отклонить решение, научите меня, лол.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 30 января 2020

То, что вы ищете, - это 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 ;
0 голосов
/ 30 января 2020

Вы можете l oop строк вашей временной таблицы и сохранить результаты в другой временной таблице.

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'

Ваш код, но с индикатором 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

Объявление временной таблицы для #MinMaxValues. В этой таблице будут храниться результаты для каждого столбца, пока мы будем перебирать каждую запись #TEMP_COLS.

Эта итерация может быть курсором, но, поскольку курсоры очень медленные, я предпочитаю перебирать каждую запись в #TEMP_COLS, пока наш индикатор isProcessed равен 0, что означает, что @ col получит значение. Каждое обработанное обновление записи обрабатывается текущей строки со значением 1.

...