选择与条件匹配的列名称(MS SQL Server)

时间:2013-07-19 21:26:06

标签: sql sql-server

我在MS SQL Server中有以下数据库结构: ID,Col_A,Col_B,Col_C等......

除ID之外的所有其他列都是Boolean类型。让我们举例说一下     Col_A = 1,     Col_B = 0,     Col_C = 1

我正在寻找一种方法来返回列为1的列的名称。 在此示例中,返回应类似于ID,Col_A,Col_C

将会有一个动态数量的列,因为表经常被更改以添加新列并删除旧列。

基本上,我需要与以下帖子完全相同的功能,但作为MS Sql Server查询: Select column names that match a criteria (MySQL)

我想在MS SQL Server中实现SQL Fiddle链接http://sqlfiddle.com/#!2/8f4ee/12。有什么想法我会怎么做? MS SQL Server无法识别两个函数CONCAT_WS和GROUP_CONCAT。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:0)

试试这个:

create table jtr (id varchar(36), col_a tinyint, col_b tinyint, col_c tinyint)
insert into jtr values (1, 1, 0, 1), (2, 0, 0, 1), (3, 1, 0 ,0), (4, 0, 1, 0)

CREATE TABLE #app (res tinyint)
CREATE TABLE #outmess (message varchar(1000))

DECLARE @dynsql varchar(1000)
DECLARE @colname sysname
DECLARE @mess varchar(1000)
DECLARE @id int

DECLARE #crs_tab INSENSITIVE CURSOR FOR
SELECT id FROM jtr
FOR READ ONLY

OPEN #crs_tab
FETCH NEXT FROM #crs_tab INTO @id

WHILE (@@FETCH_STATUS = 0)
BEGIN
    DECLARE #crs INSENSITIVE CURSOR FOR
    SELECT c.name FROM syscolumns c
    JOIN sysobjects o
    ON o.id = c.id
    WHERE o.name = 'jtr'
    AND o.xtype = 'U'
    AND c.type = 38
    FOR READ ONLY

    OPEN #crs
    FETCH NEXT FROM #crs INTO @colname
    WHILE (@@FETCH_STATUS = 0)
    BEGIN
        SET @dynsql = 'SELECT ' + @colname + ' FROM jtr where id = ' + CONVERT(varchar, @id)
        insert into #app
        exec (@dynsql)

        if (select res from #app) = 1
        begin
            if (@mess != '')
            begin
                set @mess = @mess + ', ' + @colname
            end
            else
            begin
                set @mess = @colname
            end
        end

        delete from #app
        FETCH NEXT FROM #crs INTO @colname
    END
    CLOSE #crs
    DEALLOCATE #crs
    insert into #outmess values (@mess)

    set @mess = ''
    FETCH NEXT FROM #crs_tab INTO @id
END
CLOSE #crs_tab
DEALLOCATE #crs_tab

select * from #outmess

我已经创建了一个带有以下字段的示例表JTR:ID,COL_A,COL_B,COL_C,如果您希望可以放置所需的字段数。

我在该表中放了4行。

所以我实现了两个游标,一个用于滚动JTR表,一个用于从syscolumns滚动所有列名。

对于每个值为1的列,我构建一个列名为

的消息

在临时表#outmess中,您可以找到以逗号连接的所有列值ONE。

P.S。相反,布尔我使用了tinyint。在syscolumns字段中,类型为38,关于tinyint

告诉我是否可以

答案 1 :(得分:0)

这非常简单(SQLFiddle:http://sqlfiddle.com/#!3/c44bc/1/0):

DECLARE @cmd NVARCHAR(MAX);
DECLARE @cmd_partial NVARCHAR(MAX);

SET @cmd_partial = '';

SELECT @cmd_partial = @cmd_partial + '
       CASE ' + COLUMN_NAME + '
          WHEN 1 THEN
             ''' + COLUMN_NAME + ', ''
          ELSE
             ''''
       END +'
  FROM INFORMATION_SCHEMA.COLUMNS
 WHERE TABLE_NAME = 'mytable'
   AND COLUMN_NAME <> 'id';

SET @cmd_partial = LEFT(@cmd_partial, LEN(@cmd_partial) - 1);

SET @cmd = '
WITH cols AS (
 SELECT id,
' + @cmd_partial + ' AS columns
FROM mytable
)
  SELECT id, CASE
                WHEN LEN(columns) > 0 THEN
                   LEFT(columns, LEN(columns) - 1)
                ELSE
                   ''''
             END
    FROM cols;
';

EXEC (@cmd);

答案 2 :(得分:0)

下面的查询与您的MySql查询非常相似。 Working demo

查询:

  declare @sql nvarchar(max)
  select @sql = ''
  select @sql = @sql +   case WHEN len(@sql) = 0 THEN '' ELSE ' + ' END + 
  ' case when ' + C.Name  + ' = 1 then '',' + C.Name  + ''' else '''' end'
  FROM
    sys.columns c
    inner join sys.objects o on o.Object_ID = c.Object_ID 
  WHERE
    o.Name ='yourtable'
    AND C.Name!='id'


  select @sql = 'select ID, Stuff(' + @sql + ',1,1,N'''') from yourtable'
  exec (@sql)

答案 3 :(得分:0)

可能的解决方案之一是动态sql通过进一步连接来解析数据:

declare @stmt nvarchar(max)

select @stmt = IsNull(@stmt + ', ', '') + quotename(name)
from sys.columns
where object_id = object_id('TableName') and name != 'ID'
order by column_id

set @stmt = ';with du as (
    select *
    from TableName d
        unpivot (Val for Name in (' + @stmt + ')) u
)
select d.ID, IsNull(left(Cols, len(Cols) - 1), ''<None>'') as ColumnsSet
from (select ID from TableName) d
    cross apply (select (select Name + '', ''
        from du
        where Val = 1 and ID = d.ID
        for xml path ('''')) as Cols) c'

print @stmt
exec(@stmt)

对于以下数据:

create table TableName (ID int, Col1 bit, Col2 bit, Col3 bit)
insert into TableName values
    (1, 0, 1, 1)
    ,(2, 1, 1, 1)
    ,(3, 1, 0, 0)
    ,(4, 0, 0, 0)

输出是:

ID          ColumnsSet
----------- -----------------
1           Col2, Col3
2           Col1, Col2, Col3
3           Col1
4           <None>