TSQL:条件查询问题
TSQL : conditional query issue
我需要创建一个标志来标识满足以下条件的所有 Room_IDs
:
- 一个 "Qc-"
Status
出现在一个 Hotel_ID
中。
- "Qc-"
Status
有对应的非 "Qc-" Status
(例如
'qc-occupied' & 'occupied').
- "Qc-"
Status
必须有一个比 Room_ID
小的 Room_ID
非 "Qc-" Status
。 (例如 Status
= 'qc-occupied' 有一个 Room_ID
=1 和 Status
= 'occupied' 有一个 Room_ID
= 5)
这是一个简化的 table (tableX) 我用的例子是:
**Hotel_ID Room_Id Status**
1 1 vacant
1 2 qc-occupied
1 3 vacant
2 1 occupied
2 2 qc-vacant
2 3 vacant
3 1 qc-vacant
4 1 vacant
4 2 occupied
4 3 qc-vacant
5 1 vacant
我需要以下结果:
**Hotel_ID Room_Id Status flag**
1 1 vacant 0
1 2 qc-occupied 0
1 3 vacant 0
2 1 occupied 0
2 2 qc-vacant 1
2 3 vacant 1
3 1 qc-vacant 0
4 1 vacant 0
4 2 occupied 0
4 3 qc-vacant 0
5 1 vacant 0
提前致谢!
这是将需求字面翻译成相当不优雅的代码。它当然可以改进,例如通过删除您的第一个要求("qc-" present.),因为它隐含在其他两个要求中。第二个要求隐含在第三个中,允许另一个改进。
-- Sample data.
declare @TableX as Table ( Hotel_Id Int, Room_Id Int, Stat VarChar(16) );
insert into @TableX ( Hotel_Id, Room_Id, Stat ) values
( 1, 1, 'vacant' ), ( 1, 2, 'qc-occupied' ), ( 1, 3, 'vacant' ),
( 2, 1, 'occupied' ), ( 2, 2, 'qc-vacant' ), ( 2, 3, 'vacant' ),
( 3, 1, 'qc-vacant' ),
( 4, 1, 'vacant' ), ( 4, 2, 'occupied' ), ( 4, 3, 'qc-vacant' ),
( 5, 1, 'vacant' );
select * from @TableX;
-- Literal translation of requirements.
declare @False as Bit = 0, @True as Bit = 1;
select Hotel_Id, Room_Id, Stat,
QC_In_Hotel, QC_And_NonQC_In_Hotel, QC_Precedes_NonQC_In_Hotel,
case when QC_In_Hotel = @True and QC_And_NonQC_In_Hotel = @True and
QC_Precedes_NonQC_In_Hotel = @True then @True else @False end as Flag
from (
select Hotel_Id, Room_Id, Stat,
-- Req: a "Qc-" Status is present within one Hotel_ID.
case when exists ( select 42 from @TableX as I
where I.Hotel_Id = O.Hotel_Id and I.Stat like 'qc-%' )
then @True else @False end as QC_In_Hotel,
-- Req: the "Qc-" Status has a corresponding non "Qc-" Status (e.g. 'qc-occupied' & 'occupied').
case when exists ( select 42 from @TableX as I
where I.Hotel_Id = O.Hotel_Id and
( ( I.Stat like 'qc-' + O.Stat ) or ( O.Stat like 'qc-' + I.Stat ) ) )
then @True else @False end as QC_And_NonQC_In_Hotel,
-- Req: the "Qc-" Status has to have a to have a smaller Room_ID than the non "Qc-" Status.
case when exists ( select 42 from @TableX as I
where I.Hotel_Id = O.Hotel_Id and
( ( I.Room_Id < O.Room_Id and I.Stat like 'qc-' + O.Stat ) or
( O.Room_Id < I.Room_Id and O.Stat like 'qc-' + I.Stat ) ) )
then @True else @False end as QC_Precedes_NonQC_In_Hotel
from @TableX as O ) as PH
order by Hotel_Id, Room_Id;
我需要创建一个标志来标识满足以下条件的所有 Room_IDs
:
- 一个 "Qc-"
Status
出现在一个Hotel_ID
中。 - "Qc-"
Status
有对应的非 "Qc-"Status
(例如 'qc-occupied' & 'occupied'). - "Qc-"
Status
必须有一个比Room_ID
小的Room_ID
非 "Qc-"Status
。 (例如Status
= 'qc-occupied' 有一个Room_ID
=1 和Status
= 'occupied' 有一个Room_ID
= 5)
这是一个简化的 table (tableX) 我用的例子是:
**Hotel_ID Room_Id Status**
1 1 vacant
1 2 qc-occupied
1 3 vacant
2 1 occupied
2 2 qc-vacant
2 3 vacant
3 1 qc-vacant
4 1 vacant
4 2 occupied
4 3 qc-vacant
5 1 vacant
我需要以下结果:
**Hotel_ID Room_Id Status flag**
1 1 vacant 0
1 2 qc-occupied 0
1 3 vacant 0
2 1 occupied 0
2 2 qc-vacant 1
2 3 vacant 1
3 1 qc-vacant 0
4 1 vacant 0
4 2 occupied 0
4 3 qc-vacant 0
5 1 vacant 0
提前致谢!
这是将需求字面翻译成相当不优雅的代码。它当然可以改进,例如通过删除您的第一个要求("qc-" present.),因为它隐含在其他两个要求中。第二个要求隐含在第三个中,允许另一个改进。
-- Sample data.
declare @TableX as Table ( Hotel_Id Int, Room_Id Int, Stat VarChar(16) );
insert into @TableX ( Hotel_Id, Room_Id, Stat ) values
( 1, 1, 'vacant' ), ( 1, 2, 'qc-occupied' ), ( 1, 3, 'vacant' ),
( 2, 1, 'occupied' ), ( 2, 2, 'qc-vacant' ), ( 2, 3, 'vacant' ),
( 3, 1, 'qc-vacant' ),
( 4, 1, 'vacant' ), ( 4, 2, 'occupied' ), ( 4, 3, 'qc-vacant' ),
( 5, 1, 'vacant' );
select * from @TableX;
-- Literal translation of requirements.
declare @False as Bit = 0, @True as Bit = 1;
select Hotel_Id, Room_Id, Stat,
QC_In_Hotel, QC_And_NonQC_In_Hotel, QC_Precedes_NonQC_In_Hotel,
case when QC_In_Hotel = @True and QC_And_NonQC_In_Hotel = @True and
QC_Precedes_NonQC_In_Hotel = @True then @True else @False end as Flag
from (
select Hotel_Id, Room_Id, Stat,
-- Req: a "Qc-" Status is present within one Hotel_ID.
case when exists ( select 42 from @TableX as I
where I.Hotel_Id = O.Hotel_Id and I.Stat like 'qc-%' )
then @True else @False end as QC_In_Hotel,
-- Req: the "Qc-" Status has a corresponding non "Qc-" Status (e.g. 'qc-occupied' & 'occupied').
case when exists ( select 42 from @TableX as I
where I.Hotel_Id = O.Hotel_Id and
( ( I.Stat like 'qc-' + O.Stat ) or ( O.Stat like 'qc-' + I.Stat ) ) )
then @True else @False end as QC_And_NonQC_In_Hotel,
-- Req: the "Qc-" Status has to have a to have a smaller Room_ID than the non "Qc-" Status.
case when exists ( select 42 from @TableX as I
where I.Hotel_Id = O.Hotel_Id and
( ( I.Room_Id < O.Room_Id and I.Stat like 'qc-' + O.Stat ) or
( O.Room_Id < I.Room_Id and O.Stat like 'qc-' + I.Stat ) ) )
then @True else @False end as QC_Precedes_NonQC_In_Hotel
from @TableX as O ) as PH
order by Hotel_Id, Room_Id;