从 SQL 服务器 table - Return sys.columns ColumnName 中的多个列中查找 MIN 值

Find MIN value from multiple columns in a SQL Server table - Return sys.columns ColumnName

规格:SSMS 2012

Table:7 列,1 个 ID 列(NOT NULL)和 6 个日期列(NULL)

table中有几千行:

ID|Date1|Date2|Date3|Date4|Date5|Date6

.

我正在尝试在所有 6 个日期列中查找 MIN(DATE);但是,我无法忘记日期列名称(sys.columns 值)。这是报告哪个列具有最低日期所必需的。

所有日期列都可以有 NULL 值。

我愿意创建另一个列来报告 MIN(sys.columns) 名称,或者为每个日期列添加一个 T/F 列,其中 'T' 对应于最低日期柱子。显然,在计算 MIN(DATE) 时应避免使用 NULL。

我在想可能需要一个 UNPIVOT。任何帮助,将不胜感激。感谢您提前查看。

这是我想出的,但如果您定期 运行 它可能会被清理以提高效率。

首先,这是我为此创建的 table 变量:

DECLARE @dates TABLE (
id INT,
date1 DATE,
date2 DATE,
date3 DATE,
date4 DATE,
date5 DATE,
date6 DATE)

INSERT @dates VALUES
(1,'2014-12-31',NULL,'2014-03-12','2014-04-20','2014-02-10','2014-01-06'),
(2,'2015-11-08','2014-03-18','2014-07-14',NULL,'2014-04-15','2014-01-17'),
(3,'2015-12-13','2014-11-11','2014-09-18','2014-09-01','2014-06-24','2014-01-28'),
(4,'2016-04-24','2014-12-20','2015-04-14','2015-12-27','2015-05-14',NULL),
(5,'2016-08-22','2015-11-16','2016-03-26','2016-08-31','2015-09-25','2015-02-20'),
(6,NULL,'2016-01-13','2016-08-02','2016-10-08',NULL,'2016-05-28'),
(7,'2016-09-22','2016-01-25','2017-03-06','2016-10-19','2017-02-03','2016-06-14'),
(8,'2017-05-21','2017-01-14','2017-11-07','2017-01-22','2017-02-15','2017-10-30'),
(9,'2017-12-15','2017-05-06',NULL,'2017-12-26','2017-11-07','2017-11-01')

这是我提出的逆透视查询。

SELECT
    col_val,
    date_val
FROM (
    SELECT
        SUBSTRING(date_val,0,charindex(':',date_val,0)) AS col_val,
        CAST(SUBSTRING(date_val,charindex(':',date_val,0)+1,10) AS DATE) AS date_val,
        ROW_NUMBER() OVER (ORDER BY CAST(SUBSTRING(date_val,charindex(':',date_val,0)+1,10) AS DATE) /*date_val*/) AS rn
    FROM (
        SELECT
            'date1:' + CAST(MIN(date1) AS NVARCHAR(MAX)) AS date1,
            'date2:' + CAST(MIN(date2) AS NVARCHAR(MAX)) AS date2,
            'date3:' + CAST(MIN(date3) AS NVARCHAR(MAX)) AS date3,
            'date4:' + CAST(MIN(date4) AS NVARCHAR(MAX)) AS date4,
            'date5:' + CAST(MIN(date5) AS NVARCHAR(MAX)) AS date5,
            'date6:' + CAST(MIN(date6) AS NVARCHAR(MAX)) AS date6
        FROM @dates) dates
    UNPIVOT (date_val FOR dates IN (date1, date2, date3, date4, date5, date6)) AS unpvt
    ) tbl
WHERE rn = 1

所以这成功了。可能不是最干净的代码,但我添加了 GROUP BY [id] 并做了一个 MIN(date) INNER JOIN:

DECLARE @dates TABLE (
id Varchar(50),
date1 DATE,
date2 DATE,
date3 DATE,
date4 DATE)

INSERT @dates VALUES
(1,'2014-12-31',NULL,'2014-03-12','2014-04-20'),
(2,'2015-11-08','2014-03-18','2014-07-14',NULL),
(3,'2015-12-13','2014-11-11','2014-09-18','2014-09-01'),
(4,'2016-04-24','2014-12-20','2015-04-14','2015-12-27'),
(5,'2016-08-22','2015-11-16','2016-03-26','2016-08-31'),
(6,NULL,'2016-01-13','2016-08-02','2016-10-08'),
(7,'2016-09-22','2016-01-25','2017-03-06','2016-10-19'),
(8,'2017-05-21','2017-01-14','2017-11-07','2017-01-22'),
(9,'2017-12-15','2017-05-06',NULL,'2017-12-26')

SELECT id,col_val,date_val
INTO #TableName
FROM (SELECT id,
    SUBSTRING(date_val,0,charindex(':',date_val,0)) AS col_val,
    CAST(SUBSTRING(date_val,charindex(':',date_val,0)+1,10) AS DATE) AS date_val,
    ROW_NUMBER() OVER (ORDER BY CAST(SUBSTRING(date_val,charindex(':',date_val,0)+1,10) AS DATE) /*date_val*/) AS rn
    FROM (SELECT id,
        'date1:' + CAST(MIN(date1) AS NVARCHAR(MAX)) AS date1,
        'date2:' + CAST(MIN(date2) AS NVARCHAR(MAX)) AS date2,
        'date3:' + CAST(MIN(date3) AS NVARCHAR(MAX)) AS date3,
        'date4:' + CAST(MIN(date4) AS NVARCHAR(MAX)) AS date4
        FROM @dates
        GROUP BY id
        ) dates
    UNPIVOT (date_val FOR dates IN (date1, date2, date3, date4)) AS unpvt
    ) tbl

Select tbl.*
From #TableName tbl
Inner Join
(Select id,MIN(date_val) min_date_val From #TableName Group By id) tbl1
On tbl1.id=tbl.id
Where tbl1.min_date_val=tbl.date_val

您也可以考虑使用 VALUES 关闭而不是 UNPIVOT。对我来说似乎更干净 "more standard"。看看吧。

Table 变量(谢谢,安德鲁):

DECLARE @dates TABLE (
id INT,
date1 DATE,
date2 DATE,
date3 DATE,
date4 DATE,
date5 DATE,
date6 DATE)

INSERT @dates VALUES
(1,'2014-12-31',NULL,'2014-03-12','2014-04-20','2014-02-10','2014-01-06'),
(2,'2015-11-08','2014-03-18','2014-07-14',NULL,'2014-04-15','2014-01-17'),
(3,'2015-12-13','2014-11-11','2014-09-18','2014-09-01','2014-06-24','2014-01-28'),
(4,'2016-04-24','2014-12-20','2015-04-14','2015-12-27','2015-05-14',NULL),
(5,'2016-08-22','2015-11-16','2016-03-26','2016-08-31','2015-09-25','2015-02-20'),
(6,NULL,'2016-01-13','2016-08-02','2016-10-08',NULL,'2016-05-28'),
(7,'2016-09-22','2016-01-25','2017-03-06','2016-10-19','2017-02-03','2016-06-14'),
(8,'2017-05-21','2017-01-14','2017-11-07','2017-01-22','2017-02-15','2017-10-30'),
(9,'2017-12-15','2017-05-06',NULL,'2017-12-26','2017-11-07','2017-11-01');

查询:

WITH Unpivoted as (
SELECT [rowId], [date], [colId]
  FROM @dates
CROSS APPLY ( VALUES
              (id, date1, 1)
             ,(id, date2, 2)
             ,(id, date3, 3)
             ,(id, date4, 4)
             ,(id, date5, 5)
             ,(id, date6, 6)
             ) 
          AS T([rowId], [date], [colId])
)
, MinDate as (
SELECT [rowId], MIN([date]) as [date]
  FROM Unpivoted
  GROUP BY [rowId]
  )

  SELECT M.[rowId]
        ,M.[date]
        ,U.[colId]
  FROM [MinDate] as M
  JOIN Unpivoted as U
    ON M.[rowId] = u.[rowId]
   AND M.[date]  = u.[date]