这是不可能的,原因有二。
- 您不能在查询中动态更改列名
- 您不能在单个列中混合多种数据类型。
但是为了让你得到类似于你正在寻找的东西,你可以像这样翻转问题:
SQL小提琴
MS SQL Server 2008 架构设置:
CREATE TABLE dbo.a(c1 INT, c2 INT, c3 DATE);
INSERT INTO dbo.a VALUES(1,2,'2013-04-05'),(4,5,'2010-11-10'),(7,8,'2012-07-09');
查询 1:
SELECT
MIN(c1) c1_min,MAX(c1) c1_max,
MIN(c2) c2_min,MAX(c2) c2_max,
MIN(c3) c3_min,MAX(c3) c3_max
FROM dbo.a;
结果:
| C1_MIN | C1_MAX | C2_MIN | C2_MAX | C3_MIN | C3_MAX |
|--------|--------|--------|--------|------------|------------|
| 1 | 7 | 2 | 8 | 2010-11-10 | 2013-04-05 |
这为您提供了单行中的所有列最小值和最大值。(它还不是动态的。留在我身边......)
为了使其更具可读性,您可以使用一种像这样的 UNPIVOT:
查询 2:
SELECT
CASE X.FN WHEN 1 THEN 'MIN' ELSE 'MAX' END AS FN,
CASE X.FN WHEN 1 THEN c1_min ELSE c1_max END AS c1,
CASE X.FN WHEN 1 THEN c2_min ELSE c2_max END AS c2,
CASE X.FN WHEN 1 THEN c3_min ELSE c3_max END AS c3
FROM(
SELECT
MIN(c1) c1_min,MAX(c1) c1_max,
MIN(c2) c2_min,MAX(c2) c2_max,
MIN(c3) c3_min,MAX(c3) c3_max
FROM dbo.a)AGG
CROSS JOIN (VALUES(1),(2))X(FN)
ORDER BY X.FN;
结果:
| FN | C1 | C2 | C3 |
|-----|----|----|------------|
| MIN | 1 | 2 | 2010-11-10 |
| MAX | 7 | 8 | 2013-04-05 |
现在要使其动态化,我们必须动态构建该查询,如下所示:
查询 3:
DECLARE @cmd NVARCHAR(MAX);
SET @cmd =
'SELECT CASE X.FN WHEN 1 THEN ''MIN'' ELSE ''MAX'' END AS FN'+
(SELECT ',CASE X.FN WHEN 1 THEN '+name+'_min ELSE '+name+'_max END AS '+name
FROM sys.columns WHERE object_id = OBJECT_ID('dbo.a')
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)')+
' FROM(SELECT '+
STUFF((SELECT ',MIN('+name+') '+name+'_min,MAX('+name+') '+name+'_max'
FROM sys.columns WHERE object_id = OBJECT_ID('dbo.a')
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,'')+
' FROM dbo.a)AGG CROSS JOIN (VALUES(1),(2))X(FN) ORDER BY X.FN;';
EXEC(@cmd);
结果:
| FN | C1 | C2 | C3 |
|-----|----|----|------------|
| MIN | 1 | 2 | 2010-11-10 |
| MAX | 7 | 8 | 2013-04-05 |
此查询在运行时获取表的列,动态构建适当的查询并执行它。它在三个位置包含表名 ('dbo.a')。如果您希望它与不同的表一起使用,则需要替换所有三个表。