Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用子查询定义列别名_Sql_Sql Server_Subquery_Alias - Fatal编程技术网

Sql 使用子查询定义列别名

Sql 使用子查询定义列别名,sql,sql-server,subquery,alias,Sql,Sql Server,Subquery,Alias,为了清楚起见,我在下面简化了两个表格。一个存储数据值,另一个定义数据的单位和类型。一些测试有一个结果,其他测试可能有更多(我的实际表格有结果1-10): 表“测试”: ID Result1 Result2 TestType(FK to TestTypes Type) ---------- ------------ ----------- ----------- 1001 50 29

为了清楚起见,我在下面简化了两个表格。一个存储数据值,另一个定义数据的单位和类型。一些测试有一个结果,其他测试可能有更多(我的实际表格有结果1-10):

表“测试”:

ID            Result1        Result2        TestType(FK to TestTypes Type)
----------    ------------   -----------    -----------
1001           50            29             1
1002           90.9          NULL           2
1003           12.4          NULL           2
1004           20.2          30             1
表“TestTypes”:

Type        TestName         Result1Name    Result1Unit   Result2Name     Result2Unit   ..........
-------     ---------        ------------   -----------   ------------    -----------
1           Temp Calib.      Temperature    F             Variance        %
2           Clarity          Turbidity      CU            NULL            NULL
当我连接两个表时,我想使用ResultXName作为列别名。换句话说,如果用户希望查看所有类型1“临时校准”测试,则数据的格式如下:

Temperature      Variance         
------------     -----------
50 F             10.1%
20.2 F           4.4%
或者,如果他们查看类型2,它只使用1个结果,应该忽略NULL:

Turbidity
----------
90.9 CU
12.4 CU
我已经成功地将两列表格组合在一起:

SELECT CONCAT(Result1, ' ', ISNULL(Result1Unit, ''))
FROM Tests 
INNER JOIN TestTypes ON Tests.TestType = TestTypes.Type
但是我不知道如何使用TestName作为新的列别名。这是我一直在尝试使用子查询的内容,但似乎AS子句中不允许使用子查询:

SELECT CONCAT(Result1, ' ', ISNULL(Result1Unit, '')) AS (SELECT TOP(1) Result1Name FROM TestTypes WHERE Type = 1)
FROM Tests 
INNER JOIN TestTypes ON Tests.TestType = TestTypes.Type

有没有其他方法可以使用?或者我需要重新构建数据以实现这一点?我正在使用MSSQL

是的,通过仔细构造动态SQL字符串,这可以完全自动化。本解决方案和参考文献中的要点如下所示

  • (第1节)
  • 获取
    ResultXName
    by的新列名(第2-1节)
  • 为新列追加条款(第2-2节)
  • 注意:1.虽然动态表模式通常被认为是一种糟糕的设计,但有时人们只是奉命这样做。因此,我不怀疑这项规定是否足够

    注意任意字符串执行的安全问题。根据您的用例,可能需要额外的字符串过滤器

    测试数据集

    use [testdb];
    GO
    
    if OBJECT_ID('testdb..Tests') is not null
        drop table testdb..Tests;
    create table [Tests] (
        [ID] int,
        Result1 float,
        Result2 float,
        TestType int
    )
    insert into [Tests]([ID], Result1, Result2, TestType)
    values (1001,50,29,1),
           (1002,90.9,NULL,2),
           (1003,12.4,NULL,2),
           (1004,20.2,30,1);
    
    if OBJECT_ID('testdb..TestTypes') is not null
        drop table testdb..TestTypes;
    create table [TestTypes] (
        [Type] int,
        TestName varchar(50),
        Result1Name varchar(50),
        Result1Unit varchar(50),
        Result2Name varchar(50),
        Result2Unit varchar(50)
    )
    insert into [TestTypes]([Type], TestName, Result1Name, Result1Unit, Result2Name, Result2Unit)
    values (1,'Temp Calib.','Temperature','F','Variance','%'),
           (2,'Clarity','Turbidity','CU',NULL,NULL);
    
    --select * from [Tests];
    --select * from [TestTypes];
    
    解决方案

    /* Input Parameter */
    declare @type_no int = 1;
    
    /* 1. determine the number of Results */
    
    declare @n int;
    
    -- If there are hundreds of results please use the method as of (2-1)
    select @n = LEN(COALESCE(LEFT(Result1Name,1),'')) 
              + LEN(COALESCE(LEFT(Result2Name,1),''))
    FROM [TestTypes]
    where [Type] = @type_no;
    
    /* 2. build dynamic query string */
    
    -- cast type number as string
    declare @s_type varchar(10) = cast(@type_no as varchar(10));
    -- sql query string
    declare @sql nvarchar(max) = '';
    declare @sql_colname nvarchar(max) = '';    
    -- loop variables
    declare @i int = 1;  -- loop index
    declare @s varchar(10);  -- stringified @i
    declare @colname varchar(max);  -- new column name
    
    set @sql += '
    select
        L.[ID]';
    
    -- add columns one by one
    while @i <= @n begin
    
        set @s = cast(@i as varchar(10));
    
        -- (2-1) find the new column name
        SET @sql_colname = N'select @colname = Result' + @s + 'Name
            from [TestTypes]
            where [Type] = ' + @s_type;
    
        EXEC SP_EXECUTESQL 
            @Query = @sql_colname,
            @Params = N'@colname varchar(max) OUTPUT',
            @colname = @colname OUTPUT;
    
        -- (2-2) sql clause of the new column
        set @sql += ',
          cast(L.Result' + @s + ' as varchar(10)) + '' '' + R.Result' + @s + 'Unit as [' + @colname + ']'
    
        -- next Result
        set @i += 1
    end
    
    set @sql += '
        into [ans]
        from [Tests] as L
        inner join [TestTypes] as R
            on L.TestType = R.Type
        where R.[Type] = ' + @s_type;
    
    /* execute */
    
    print @sql;  -- check the query string
    
    if OBJECT_ID('testdb..ans') is not null
        drop table testdb..ans;
    exec sp_sqlexec @sql;
    
    /* show */
    select * from [ans];
    

    在debian 10上的SQL Server 2017(linux docker image,最新版本)上进行测试

    在查询(可能是动态的)中执行此操作将非常困难。我会尝试将所有列合并,然后在SSRS(显示/隐藏规则列)等报告工具中格式化。查询无法很好地处理不同数量的列和数据类型。哦,您确实不希望在列中组合数字和单位。这意味着它现在是一个字符串而不是一个数字。我知道你把90.9CU+12.4CU看作是103.3CU,但这不是SQL中的工作方式。这将是字符串连接与加法。同样,您可以在报告工具中使用一个额外的列作为显示列来执行此操作,但将值保存在它们自己的列中。它仅用作显示器。也就是说,我可能会将这两列分开,以防以后我想用这些数据进行计算。我正在使用点火SCADA软件-我确实可以通过脚本控制列名。我的计划B是使用编写一个python脚本来相应地更新标题。10.1%的差异是如何产生的?
    | ID   | Temperature | Variance |
    |------|-------------|----------|
    | 1001 | 50 F        | 29 %     |
    | 1004 | 20.2 F      | 30 %     |
    
    /* the query string */
    
    select
        L.[ID],
          cast(L.Result1 as varchar(10)) + ' ' + R.Result1Unit as [Temperature],
          cast(L.Result2 as varchar(10)) + ' ' + R.Result2Unit as [Variance]
    into [ans]
    from [Tests] as L
    inner join [TestTypes] as R
        on L.TestType = R.Type
    where R.[Type] = 1