如何联接选择具有条件的重复项的表



我有 2 个表

TicketHeaders TH

ticketID>amount>600400
1
2 ;">900
3
SELECT TH.ticketID, TH.Amount, COALESCE(TB_M.SellerName, TB_T.SellerName)
FROM TH
LEFT JOIN TB TB_M ON TH.ticketID = TB_M.ticketID AND TB_M.SellerType = 'Manager'
LEFT JOIN TB TB_T ON TH.ticketID = TB_T.ticketID AND TB_T.SellerType <> 'Manager'

根据所述的 2.5 版,您似乎无法使用row_number()解决方案。您可以使用单个内部联接来解决此问题。我不知道避免额外加入火鸟是否有任何好处。

select ticketID, min(Amount) as Amount,
case min(case SellerType when 'Manager' then 1 else 2 end) when 1
then min(case SellerType =  'Manager' then SellerName end)
else min(case SellerType <> 'Manager' then SellerName end)
end SellerName
from TH th inner join TB tb on tb.ticketID = th.ticketID
group by ticketID

另一个好处是,这将适用于不同卖家的更大层次结构(通过添加新案例)。但是,如果在一个级别上有多个卖家,则不起作用。

在这种情况下我会使用 row_number():

with _cte as (
SELECT TH.ticketID, 
TH.Amount, 
TB.SellerName, 
row_number() over (partition by TH.ticketID order by case when SellerType = 'Manager' then 0 else 1 end) as rn
FROM TH
LEFT JOIN TB ON TH.ticketID = TB.ticketID
)
select ticketID, Amount, SellerName
from _cte 
where rn = 1

A.S.我认为您的问题尚未明确定义:

我只需要为该特定工单选择经理

如果有很多行,但有两个或更多经理怎么办?零经理?没有经过深思熟虑,就像保证SQL服务器永远不会允许插入此类数据一样,这是一个等待发生的错误。

我还认为SellerType最好是一个整数字段,一个Seller_types字典表的外键——既是因为整数字段更容易index编辑和比较join表,也因为这样可以让你以后随心所欲地重命名"功能角色"(或者像你被老板做的那样), 无需更改任何内容:您的Seller_types可以有额外的列,例如整数role_priority,甚至类似于max_persons_of_type_in_one_ticket(例如,您的老板可能会决定一张票上可以有两个经理,或者一个经理和一个副经理,然后不超过四个实习生)。

但回到问题,还有一种方法可以做到这一点。它实际上会为表中的每一行运行correlated sub-queryTicketHeaders因此,如果您执行数千行的"长"选择,它可能会更慢。特别是如果你保留了 Firebird 的默认小内存缓存(请参阅有关配置 Firebird 和 ib-aid.com 上宽松配置的文章)。

另一方面,它类似于"做一次就忘记",使您的查询更简单,从而减少您将来出错的机会。在短(100 行或更少)查询中,速度惩罚可能不明显。而且,如果您根本不查询该新列,也不会受到任何惩罚(您不在生产中使用select *查询,是吗?

所以,代码,最后:db<>小提琴在这里

create table Ticket_Headers (
ticket_id integer primary key, 
amount integer not null
)
create table Ticket_Body (
ticket_id integer 
REFERENCES Ticket_Headers(ticket_id) 
ON DELETE CASCADE
ON UPDATE CASCADE, 
Seller_Name varchar(20) not null,
Seller_Type varchar(20) not null,
CONSTRAINT TicketBody_PK PRIMARY KEY (ticket_id, Seller_Name)
)  
create index idx_TicketBody_Type on Ticket_Body(Seller_Type)
insert into Ticket_Headers
select 1, 600 from rdb$database union all
select 2, 900 from rdb$database union all
select 3, 400 from rdb$database 
受影响的 3 行
insert into Ticket_body
select 1, 'Karen', 'Manager' from rdb$database union all
select 1, 'James', 'Trainee' from rdb$database union all
select 2, 'John',  'Manager' from rdb$database union all
select 3, 'James', 'Trainee' from rdb$database 
受影响的 4 行
select * from Ticket_Headers
TICKET_ID |量 --------: |-----: 1 |   600 2 |   900 3 |   400
select * from Ticket_Body 
TICKET_ID |SELLER_NAME |SELLER_TYPE --------: |:---------- |:---------- 1 |凯伦 |经理    1 |詹姆斯 |实习    2 |约翰 |经理    3 |詹姆斯 |实习生
select * from Ticket_Headers TH, Ticket_Body TB where TH.ticket_id = TB.ticket_ID
TICKET_ID |金额 |TICKET_ID |SELLER_NAME |SELLER_TYPE --------: |-----: |--------: |:---------- |:---------- 1 |   600 |        1 |凯伦 |经理    1 |   600 |        1 |詹姆斯 |实习    2 |   900 |        2 |约翰 |经理    3 |   400 |        3 |詹姆斯 |实习生
alter table Ticket_Headers
add Seller_Top computed by 
( -- this parenthesis is required by COMPUTED BY SQL syntax
( -- this parenthesis is required to coerce SELECT from query to expression 
select First(1) TB.Seller_Name
from Ticket_Body TB
where TB.ticket_id = Ticket_Headers.ticket_id
order by TB.Seller_type /* Descending - if other order to be needed */ 
) 
)
select * from Ticket_Headers
TICKET_ID |金额 |SELLER_TOP --------: |-----: |:--------- 1 |   600 |凯伦     2 |   900 |John      3 |   400 |詹姆斯

上述Seller_types.role_priority将更加灵活,因此对于这样的order-by来说是面向未来的方法。

相关内容

  • 没有找到相关文章

最新更新