从 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]
规格: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]