Sql 应用程序右侧的聚合不能引用左侧的列

Sql 应用程序右侧的聚合不能引用左侧的列,sql,sql-server,Sql,Sql Server,我正在尝试理解一个包含2000个表的xBase类型的数据库。我希望使用“SELECT into tmpDBF”语句逐个导入表,然后提取我想知道的内容,如表结构和每个列的值范围,而不是将它们全部导入SQL Server数据库。然后,在导入下一个表时,我希望能够对不同结构的tmpDBF表运行相同的查询 我希望使用交叉应用程序来实现这一点,但我遇到了上面的错误消息 select cols.column_name 'Name', cols.data_type 'Type', mv.minV 'Minim

我正在尝试理解一个包含2000个表的xBase类型的数据库。我希望使用“SELECT into tmpDBF”语句逐个导入表,然后提取我想知道的内容,如表结构和每个列的值范围,而不是将它们全部导入SQL Server数据库。然后,在导入下一个表时,我希望能够对不同结构的tmpDBF表运行相同的查询

我希望使用交叉应用程序来实现这一点,但我遇到了上面的错误消息

select cols.column_name 'Name', cols.data_type 'Type', mv.minV 'Minimum'
  from information_schema.columns cols
  cross apply (select MIN(cols.column_name) minV FROM tmpDBF ) mv
  where cols.table_name = 'tmpDBF'
有没有办法重组这个问题,还是我变成了一条死胡同

10月6日增加:

给定tmpDBF

 Who     | Zip
 --------|------
 Charlie | 97689
 Foxtrot | 92143
 Delta   | 12011
我希望看到以下结果

 Name | Type    | Minimum | Maximum
 -----|---------|---------|--------
 who  | varchar | Charlie | Foxtrot
 Zip  | int     | 12011   | 96789

我意识到最小列和最大列需要转换为varchar。

尝试以下操作

select cols.column_name 'Name', cols.data_type 'Type', mv.minV 'Minimum'
      from information_schema.columns cols
      cross apply (select MIN(cols.column_name) minV FROM tmpDBF 
                    WHERE tmpDBF.CommonCol = cols.CommonCol) mv
      where cols.table_name = 'tmpDBF'

这是不可能的,原因有二

  • 不能动态更改查询中的列名
  • 不能在一个列中混合使用多个数据类型
  • 但是,为了得到与您所寻找的类似的东西,您可以像下面这样翻转问题:

    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');
    
    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 |
    
    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 |
    
    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 |
    
    查询1

    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');
    
    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 |
    
    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 |
    
    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 |
    

    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');
    
    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 |
    
    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 |
    
    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 |
    
    这将在一行中提供所有列的最小值和最大值。(这还不是动态的。跟我在一起…)

    为了使其更具可读性,您可以使用类似于以下内容的UNPIVOT:

    查询2

    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');
    
    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 |
    
    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 |
    
    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 |
    

    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');
    
    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 |
    
    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 |
    
    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 |
    
    现在要使其动态化,我们必须动态构建该查询,如下所示:

    查询3

    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');
    
    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 |
    
    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 |
    
    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 |
    

    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');
    
    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 |
    
    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 |
    
    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')。如果希望它与不同的表一起工作,则需要替换所有三个表

    我想一些例子会对你有所帮助,你想要什么还不是很清楚。你能展示一些样本数据和你期望的结果吗?