在 SQL 中交叉应用布尔值

Cross apply boolean values in SQL

我有table,我需要在下面创建一个类别列,将布尔值存储为一个类别。

我想将类别捕获为单个列,并且我不介意视图中有重复的行。我希望第一行是 return Contract,第二行是选择的其他值,相同的参考 ID。

我使用下面的查询实现了他:

select distinct t.*, tt.category
from t cross apply
     ( values ('Contracts', t.Contracts),
              ('Tender', t.Tender),
              ('Waiver', t.Waiver),
              ('Quotation', t.Quotation)
     ) tt(category, flag)
where flag = 1;

我如何捕获额外的类别 None,其中合同、投标、豁免和报价的所有实例都是 0

None 可以直接进入您的 VALUES 子句。您案例使用 case 表达式作为逻辑。或者,您可以使用 sign():

的技巧
select distinct t.*, tt.category
from t cross apply
     ( values ('Contracts', t.Contracts),
              ('Tender', t.Tender),
              ('Waiver', t.Waiver),
              ('Quotation', t.Quotation),
              ('None', 1 - sign(t.Contracts + t.Tender + t.Waiver + t.Quotation))
     ) tt(category, flag)
where flag = 1;

我猜你原来的 table 中没有重复项,所以你应该省去 SELECT DISTINCT

也许是这样的:

select distinct t.*, tt.category
from t cross apply
     ( values ('Contracts', t.Contracts),
              ('Tender', t.Tender),
              ('Waiver', t.Waiver),
              ('Quotation', t.Quotation),
              ('None', -1)
     ) tt(category, flag)
where flag = 1 or 
(Contracts = 0 and Tender = 0 and Waiver = 0 and Quotation = 0 and flag = -1);

这是我的示例 fiddle(假设您有位字段,但它也适用于 int 字段):http://sqlfiddle.com/#!18/9f8e7/1

希望以下SQL查询也能帮到您

create table myTable (
    ReferenceId int,
    Contract int,
    Tender int,
    Waiver int,
    Quotation int
)
insert into myTable select 1212,1,0,1,0
insert into myTable select 1213,1,1,0,0
insert into myTable select 1214,0,1,0,0
insert into myTable select 1215,1,0,1,0
insert into myTable select 1216,0,0,0,1
insert into myTable select 1217,0,0,1,0
insert into myTable select 1218,0,0,0,0

;with cte as (
    select 
    *,
    ISNULL(NULLIF(
        CONCAT_WS(',',
            case when Contract = 1 then 'Contract' end,
            case when Tender = 1 then 'Tender' end,
            case when Waiver = 1 then 'Waiver' end,
            case when Quotation = 1 then 'Quotation' end
        )
    ,''),'None') 
    as Category
    from myTable
)
select
    ReferenceId, Contract, Tender, Waiver, Quotation, c.val as Category
from cte
cross apply split(Category,',') as c

这里需要一个用户自定义的SQL function SPLIT,源代码可以在这里找到

输出如下

declare @t table
(
    ReferenceId int,
    Contracts bit,
    Tender bit,
    Waiver bit,
    Quotation bit
)

insert into @t(ReferenceId, Contracts, Tender, Waiver, Quotation)
values
(123, 0, 1, 0, 0), 
(234, 0, 0, 0, 1), 
(345, 0, 0, 0, 0);

select *
from
(
select ReferenceId, 
    Contracts, nullif(Tender, 0) as Tender, nullif(Waiver, 0) as Waiver, nullif(Quotation, 0) as Quotation,
    case when cast(Contracts as int)+Tender+Waiver+Quotation > 0 then cast(null as bit) else cast(0 as bit) end as [None]
from @t 
)as t
unpivot
(
    Flag for Category in (Contracts, Tender, Waiver, Quotation, [None])
) as unpv;

这很丑陋,但我认为这不是个坏主意

select *, 'contract' as category 
from t where contract=1 union
select *, 'waiver' 
from t where waiver=1 union
select *, 'tender' 
from t where tender=1 union
select *, 'quotation' 
from t where quotation=1 union
select *, 'none' 
from t where (contract+waiver+tender+quotation)=0
order by referenceid;