![](/img/trans.png)
[英]SQL/Oracle: Select min and max column values for each unique value in another column
[英]SQL - Select min and max value for each column
假設我有一個包含幾列(實際上是 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 作為一個整體旋轉,因為它有大約 50 萬行……即便如此,我認為旋轉是要走的路。 由於語法,我有點害怕它。
如果您知道任何其他方式,請分享。 如果你知道如何解決這個問題,請教我,哈哈。
提前致謝。
您可以循環臨時表的行並將結果存儲在另一個臨時表中。
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 的當前行進行處理。
您正在尋找的是 UNPIVOT。 逆透視示例
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 ;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.