如何修复生成过多行的查询?

How to fix a query that produces too many rows?

我正在为服务销售设计 Firebird 3.0 数据库,例如美容院等

数据库有 tables:

Serv - 服务列表;

ServRecs - 用于服务销售记录;

Docs - 用于服务文档;

Calc - 用于服务计算,即在特定服务中使用了哪些原始 material,原始数量 material 等;

RecsOut - 对于原始 material 输出记录(销售);

RecsIn - 对于原始 material 输入记录;

库存 - 用于原始 material 和商品的名称和属性。


Serv: Id, name, qnt, Vat...

ServRecs: Id, serv_id, Doc_id, qnt...

文档: doc_id, docN, DocDT, Summ, ...

计算: Id, serv_id, RawMat_id, qnt, unit_id...

RecsOut: id, doc_id, good_id, RecsIn_id

RecsIn: id, good_id...

库存: id, name (Rawaterial's and good's name)...

让我用一个例子来解释:
有服务单据323,里面用到2个服务:serv_id=7(理发)服务和serv_id=8(洗头)服务。由于 ServRecs table 的 qnt 字段显示 serv_id=8 的服务使用了 2 次(即 2 次洗涤,着色前后),serv_id=7 的服务仅使用了 1 次。正如 Calc table 所示,通常,在服务 #7 上使用 raw material with id=11446 15ml 和 id=11448 15ml,在服务 #8 - raw material with id=11450 10毫升。即,总使用量:原始 material 11446 - 15ml、11448 - 15ml 和 11450 - 20ml (2*10ml)。

我的查询如下所示:

select
i.id,
i.name as UsedRawMaterialName,
s.name as ServiceName,
ro.doc_id as ServiceDoc_id,
ri.cost as CostofRawMaterial,
sr.qnt as ServiceQnt,   --used service quantity, for example, 2 times washing 
sr.qnt*c.qnt as UsedRawMaterialQnt, --used service quantity*rawmaterial's used for 1 service
i.unit_k 

 from Inventory I, RecsOut ro, RecsIn ri,  calc c,  servrecs sr, serv s, Docs d, unit u,
  where
 d.doc_id= ro.doc_id and d.doc_id=sr.doc_id and d.doc_id=323  and
 s.id=c.serv_id and sr.serv_id=c.serv_id and
 c.rawmat_id=i.id and
 ro.recsIn_id=ri.id and
 i.unit_k=u.unit_k

我的目标是得到这样的结果:

但是,查询 returns 结果包含冗余记录和错误值,如下所示:

我的查询有什么问题?

更新 1: 我将“旧式 Join 语法”更改为“新式 Join 语法”,很容易发现错误出在“Join RecsOut ro on ro.id=i.id”子句中。 “New-style Join”确实比老式的更加直观。

select
 i.id,
 i.name as UsedRawMaterialName,
 s.name as ServiceName,
 ro.doc_id as ServiceDoc_id,
 ri.cost as CostofRawMaterial,
 sr.qnt as ServiceQnt,   --used service quantity, for example, 2 times washing 
 sr.qnt*c.qnt as UsedRawMaterialQnt, --used service quantity*rawmaterial's used for 1 service
 i.unit_k 
        
 from  
 Inventory I Join RecsOut ro on ro.id=i.id
             Join RecsIn ri on ro.recsin_id=ri.id 
             Join calc c on c.rawmat_id=i.id
             join ServRecs sr on sr.serv_id=c.serv_id
             Join serv s on s.id=c.serv_id
             Join doc d on d.doc_id=ro.doc_id and 
                           d.doc_id=sr.doc_id and 
                           d.doc_id=323 
             join unit u on i.unit_k=u.unit_k

@basti “New Style Join”的一个主要好处是每个 table 都可以在开发和测试期间一次引入一个。对于每个 table“加入”,很容易看出哪个关系产生了比您预期更多(或实际上更少)的记录

翻译您的代码后我发现某处可能有破损。感谢您回复评论 ...

from Inventory I
  join RecsOut ro on ro.recsIn_id=ri.id 
 -- ??? join RecsIn ri, --- ?? 
  join calc c on c.rawmat_id=i.id
  join servrecs sr on sr.serv_id=c.serv_id 
  join serv s on s.id=c.serv_id 
  join Docs d on d.doc_id= ro.doc_id 
      and d.doc_id=sr.doc_id
      and d.doc_id=323 
  join unit u on i.unit_k=u.unit_k 

不要忘记拥抱内连接、左连接和外连接