如何动态别名列?


10

我有一个表(不是我自己设计的),其中有20个变量命名的列。也就是说,根据您要查看的记录类型,该列的适用名称可以更改。

可能的列名存储在另一个表中,我可以很容易地查询它。

因此,我真正要查询的查询是这样的:

SELECT Col1 AS (SELECT ColName FROM Names WHERE ColNum = 1 and Type = @Type),
       Col2 AS (SELECT ColName FROM Names WHERE ColNum = 2 and Type = @Type)
FROM   Tbl1 
WHERE  Type = @Type

显然这是行不通的,那么如何获得类似的结果?

' 我已经尝试构建查询字符串并EXECUTE对其进行查询,但这仅返回“命令已成功完成”,并且似乎未返回行集。 事实证明,我使用了不正确的查询来构建动态SQL,因此构建了一个空字符串。SQL Server肯定正确执行了空字符串。

请注意,我之所以需要这样做,而不是简单地对列名进行硬编码,是因为列名是用户可配置的。


1
如果您将查询字符串打印,复制/粘贴到新的查询窗口并在其中执行,会发生什么?
DenisT 2014年

“用户可配置”意味着有成百上千种类型,和/或别名经常更改?如果别名相当稳定,我建议创建一系列视图。
所有行业的乔恩2014年

@DenisT,它不输出任何东西,这也许表明还有其他错误。感谢您的带头。
Hotchips

@JonofAllTrades不幸的是,尽管它们相当稳定,但它是规范的很大一部分,当用户更改软件中的某些内容时,该内容也必须在报告中进行更改。
Hotchips

@DenisT事实证明,我用于构建动态SQL的子查询不正确,并返回了空集。因此,SQL Server返回了一个空白查询,该查询已成功执行。感谢您指出PRINT命令。
Hotchips

Answers:


12

尝试以下代码:

CREATE TABLE #Names
(
    [Type] VARCHAR(50),
    ColNum SMALLINT,
    ColName VARCHAR(50),
    ColDataType VARCHAR(20)
)

INSERT  INTO #Names VALUES
('Customer', 1, 'CustomerID', 'INT'),
('Customer', 2, 'CustomerName', 'VARCHAR(50)'),
('Customer', 3, 'CustomerJoinDate', 'DATE'),
('Customer', 4, 'CustomerBirthDate', 'DATE'),
('Account', 1, 'AccountID', 'INT'),
('Account', 2, 'AccountName', 'VARCHAR(50)'),
('Account', 3, 'AccountOpenDate', 'DATE'),
('CustomerAccount', 1, 'CustomerID', 'INT'),
('CustomerAccount', 2, 'AccountID', 'INT'),
('CustomerAccount', 3, 'RelationshipSequence', 'TINYINT')


CREATE TABLE #Data
(
    [Type] VARCHAR(50),
    Col1 VARCHAR(50),
    Col2 VARCHAR(50),
    Col3 VARCHAR(50),
    Col4 VARCHAR(50),
    Col5 VARCHAR(50),
    Col6 VARCHAR(50),
    Col7 VARCHAR(50)
)

INSERT  INTO #Data VALUES
('Customer', '1', 'Mr John Smith', '2005-05-20', '1980-11-15', NULL, NULL, NULL),
('Customer', '2', 'Mrs Hayley Jones', '2009-10-10', '1973-04-03', NULL, NULL, NULL),
('Customer', '3', 'ACME Manufacturing Ltd', '2012-12-01', NULL, NULL, NULL, NULL),
('Customer', '4', 'Mr Michael Crocker', '2014-01-13', '1957-01-23', NULL, NULL, NULL),
('Account', '1', 'Smith-Jones Cheque Acct', '2005-05-25', NULL, NULL, NULL, NULL),
('Account', '2', 'ACME Business Acct', '2012-12-01', NULL, NULL, NULL, NULL),
('Account', '3', 'ACME Social Club', '2013-02-10', NULL, NULL, NULL, NULL),
('Account', '4', 'Crocker Tipping Fund', '2014-01-14', NULL, NULL, NULL, NULL),
('CustomerAccount', '1', '1', '1', NULL, NULL, NULL, NULL),
('CustomerAccount', '2', '1', '2', NULL, NULL, NULL, NULL),
('CustomerAccount', '2', '3', '2', NULL, NULL, NULL, NULL),
('CustomerAccount', '3', '2', '1', NULL, NULL, NULL, NULL),
('CustomerAccount', '3', '3', '1', NULL, NULL, NULL, NULL),
('CustomerAccount', '4', '2', '2', NULL, NULL, NULL, NULL),
('CustomerAccount', '4', '4', '1', NULL, NULL, NULL, NULL)


DECLARE @Type VARCHAR(50) = 'Account' -- Or Customer, or CustomerAccount

DECLARE @SQLText NVARCHAR(MAX) = ''

SELECT  @SQLText += 'SELECT '

SELECT  @SQLText += ( -- Add in column list, with dynamic column names.
                SELECT  'CONVERT(' + ColDataType + ', Col' + CONVERT(VARCHAR, ColNum) + ') AS [' + ColName + '],'
                FROM    #Names
                WHERE   [Type] = @Type FOR XML PATH('')
            )

SELECT  @SQLText = LEFT(@SQLText, LEN(@SQLText) - 1) + ' ' -- Remove trailing comma

SELECT  @SQLText += 'FROM #Data WHERE [Type] = ''' + @Type + ''''

PRINT   @SQLText
EXEC    sp_executesql @SQLText

这将返回SELECT语句: SELECT CONVERT(INT, Col1) AS [AccountID],CONVERT(VARCHAR(50), Col2) AS [AccountName],CONVERT(DATE, Col3) AS [AccountOpenDate] FROM #Data WHERE [Type] = 'Account'


鉴于该问题询问如何使用SQL,因此使用动态SQL是正确的答案。这也是我试图做的事情,但是不正确。
Hotchips 2014年

请记住,如果您接受用户输入并使用它来构建动态SQL,那么您确实需要关注SQL注入和清理输入。bobby-tables.com
Jonathan Van Matre 2014年

@JonathanVanMatre绝对。幸运的是,这仅供内部使用,并且所有输入均已由应用程序清除。
Hotchips 2014年

7

这听起来很适合前端显示解决方案。当您构建用于显示的结构时,查询1将拉回您的数据,查询2将拉回列名和代码中的内容,并在第二个查询中设置标头。

虽然纯SQL方法是可能的,但它将是动态SQL,并且代码维护将是一场噩梦。

另外,您可能正在寻找,sp_executesql而不仅仅是EXECUTE N'Query String'那样,可能会成功解决您的命令问题。


我同意,我绝对可以在SSRS中执行此操作,但是我目前无法使用其他报告软件执行此操作。
Hotchips
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.