0

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

除了 ID 之外的所有其他列都是布尔类型。比如说 Col_A = 1, Col_B = 0, Col_C = 1

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

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

基本上,我需要与以下帖子中完全相同的功能,但作为 MS Sql Server 查询: 选择符合条件的列名(MySQL)

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

任何帮助,将不胜感激。

4

4 回答 4

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>
于 2013-07-19T22:48:15.390 回答
0

下面的查询与您的 MySql 查询非常等价。工作演示

询问:

  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)
于 2013-07-19T22:26:36.713 回答
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 中的所有列名。

对于每一列价值 ONE,我建立一条带有列名的消息

在临时表#outmess 中,您会发现所有值为 ONE 的列以逗号连接。

PS 取而代之的是布尔值,我使用的是 tinyint。在 syscolumns 字段类型值 38 关于 tinyint

告诉我是否可以

于 2013-07-19T22:09:49.750 回答
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);
于 2013-07-19T22:16:40.547 回答