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

Sql 如何修复产生过多行的查询?,sql,firebird,Sql,Firebird,我正在为服务销售设计Firebird 3.0数据库,例如美容沙龙等 数据库包含以下表: 服务-用于服务列表 ServRecs-用于服务销售记录 文档-用于服务文档 计算-用于服务计算,即特定服务中使用的原材料、原材料数量等 记录原材料输出记录(销售) 记录原材料输入记录 库存-原材料和货物的名称和属性 服务:Id、名称、qnt、增值税 ServRecs:Id、服务Id、文档Id、qnt 文档:文档id、文档N、文档DT、摘要 计算:Id、服务Id、原始Id、qnt、单位Id 记录:身份证,医生

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

数据库包含以下表:

服务-用于服务列表

ServRecs-用于服务销售记录

文档-用于服务文档

计算-用于服务计算,即特定服务中使用的原材料、原材料数量等

记录原材料输出记录(销售)

记录原材料输入记录

库存-原材料和货物的名称和属性


服务:Id、名称、qnt、增值税

ServRecs:Id、服务Id、文档Id、qnt

文档:文档id、文档N、文档DT、摘要

计算:Id、服务Id、原始Id、qnt、单位Id

记录:身份证,医生身份证,好身份证,记录身份证

记录:id,好的id

库存:id、名称(原料和货物的名称)

让我用一个例子来解释:
有服务文档323。它使用了两种服务:serv_id=7(理发)和serv_id=8(洗发)。由于ServRecs表的qnt字段显示,serv_id=8的服务使用了2次(即2次清洗,着色前后),serv_id=7的服务仅使用了1次。如计算表所示,一般情况下,在役#7为id=11446 15ml和id=11448 15ml的原材料,在役#8为id=11450 10ml的原材料。即总使用量:原料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
我的目标是得到这样的结果:

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

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

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

我的问题出了什么问题

更新1: 我将“旧式连接语法”改为“新式连接语法”,很容易发现错误出现在“Join RecsOut ro on ro.id=I.id”子句中。“新样式联接”在视觉上确实比旧样式更具信息性

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“新样式联接”的一个主要好处是,在开发和测试期间,每个表可以一次引入一个。每个表“连接”后,很容易看出哪个关系生成的记录比预期的多(或少)

翻译你的代码告诉我可能有破损的地方。谢谢回复评论

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 

不要忘记包含内部、左侧和外部联接

——在ANSI-92 SQL标准中(大约30年前),旧样式的逗号分隔的表列表样式被正确的ANSI
JOIN
语法所取代,它的使用非常简单discouraged@basti:新风格已超过30年。请提供包含表和插入语句的DDL以及示例数据,以及该示例数据的预期结果和实际结果。尽量简化这个例子。不要使用屏幕截图,而是使用代码块和降价表。@basti“新样式联接”的一个主要好处是,在开发和测试期间,每个表可以一次引入一个。对于每个“连接”的表,很容易看出哪个关系生成的记录比您预期的多(甚至少)。转换为“新样式”表明ro在引入ri之前已连接到ri(只需重放from和where子句)从库存开始,我在ro上加入RecsOut ro。recsIn_id=ri.id--???加入recsinri,--??连接c.rawmat_id=i.id上的calc c连接sr.serv_id=c.serv_id连接s.id上的serv s连接d.doc_id=ro.doc_id=sr.doc_id和d.doc_id=sr.doc_id和d.doc_id=323连接i.unit上的单元u