求助,如何写这种业务 sql 比较好

2019-11-16 22:03:54 +08:00
 miv

做公司项目遇到一个问题。 是这样的,需要统计一些数据 a 表有字段:机构编码,渠道编码,业务值等 机构表 b 有字段:机构编码,机构名称,父级机构编码等 a 表的数据比如:100789、1、100 然后 b 表数据: 1007、广州、100, 10078、天河某区、100 等数据 因为要统计 a 表数据,并且要显示机构名称。所以 a 表 b 表需要关联 此时使用 like 进行关联匹配(机构编码无法直接等于去关联) 使用 sql 如 a.机构编码 like b.机构编码% 可是这样 a 一条数据对于了 2 个机构,数据重复了 怎么破?

3010 次点击
所在节点    程序员
24 条回复
miv
2019-11-16 22:11:14 +08:00
想上面的写法,汇总的数据会变多
需要把广州的数据,减去广州天河某区的数据才对。
因为匹配天河某区的数据也匹配到广州了,所以广州还要减去天河某区的数据,最后的数据才对。

造成这个问题是,
而且机构编码那样子。like 一下就匹配多了
miv
2019-11-16 22:13:00 +08:00
想问下这种机构编码的设计正常吗
求大佬
miv
2019-11-16 22:17:47 +08:00
在线等
miv
2019-11-16 22:22:13 +08:00
出现了这个问题,然后我相关的统计代码就需要做一个剔除操作,感觉很麻烦。
而且剔除的机构编码还是硬编码
得在代码里面写广州需要提出广州天河某区等等
感觉。。。
crclz
2019-11-17 00:18:45 +08:00
题目描述太少。隐隐约约感觉表 B 设计的有问题啊。

机构编码 | 机构名称 | 父级机构编码
- - -
1007、广州、100
10078、天河某区、100

这两行属于相同的业务概念?
reus
2019-11-17 00:33:03 +08:00
a 和 b 不需要关联,用子查询去取名字啊

select *, (
select string_agg(name, '')

)
from a
aguesuka
2019-11-17 00:33:51 +08:00
规范的话只能用表 a 的机构编码,或者父级编码去 join 表 b 的机构编码。能提出这个问题说明数据库最好玩重新设计
reus
2019-11-17 00:34:51 +08:00
a 和 b 不需要关联,用子查询去取名字啊

select *, (
select string_agg(name, '')
from b
where index(b, a) = 0
order by length(code) asc
) as name
from a

不记得 mysql 的函数名了,大概意思懂就行。
reus
2019-11-17 00:35:37 +08:00
数据表设计没大问题,只是你想错了,从 b 表取名字要用子查询,不要用关联
YUyu101
2019-11-17 00:38:45 +08:00
所以你到底要不要天河某区,如果要的话就代码里弄,不要的话就 sql 里 join 名字不带区的第一个,如果名字也没有规则,有的要省有的要市有的要区,那这什么奇葩业务啊,硬编码吧。
miv
2019-11-17 08:15:47 +08:00
@reus 看不太明白,可以详细介绍吗?如果可以这样那比较好
miv
2019-11-17 08:16:08 +08:00
@YUyu101 需要的
miv
2019-11-17 08:19:36 +08:00
@crclz 嗯,有点这个意思,所以 like 天河某区就一定 like 到广州了,数据一对二重复了
miv
2019-11-17 08:31:21 +08:00
用的是 oracle,Java
miv
2019-11-17 08:35:12 +08:00
@reus 大佬意思是,a 表拿机构名字用行内子查询,like 一下,然后根据 code 长度,优先匹配机构编码长的吗
shakoon
2019-11-17 08:46:51 +08:00
a 表机构号都是 4 位的是吧?那很简单啊,select a.*, b.机构名 from a left join b on a.机构号=b.机构号 and length(b.机构号)=4
TinyKube
2019-11-17 08:46:56 +08:00
2 次查询就好了,先查 B 表需要的数据,统计 B 表的关联字段,再查询得到 A 表数据,再 Join 到 B 表
shakoon
2019-11-17 08:49:08 +08:00
哦,a 不是 4 位啊,改一下,substr(a.机构号,0,4)=b.机构号
miv
2019-11-17 11:26:53 +08:00
SELECT
BRANCH_CODE,
SUM(SIGN_PREM_S) SIGN_PREM_S,
(
SELECT
t.branch_code
FROM
SYSTEM_BRANCH t
WHERE
PARENT_BRANCH = '01'
AND g.branch_code LIKE t.BRANCH_CODE || '%'
AND rownum = 1
ORDER BY
length(branch_code) DESC
) as branch_code
FROM
STAT_REPORT_HOME g
WHERE
TO_CHAR (g.ANNUAL_DAY, 'yyyymmdd') = '20191116'
GROUP BY
BRANCH_CODE
这个是一部分 sql,按照楼上说的
用行内子查询,不过 oracle 提示 order by 缺少右括号
求助
miv
2019-11-17 12:03:50 +08:00
问题已解决,参考楼上老哥的方法,行内子查询。
解决过程中遇到 2 个问题。
1,子查询使用 order by 提示缺少右括号,需要用 select 包装一层
2,如上面的 sql,按照 1 做法,还是出现 g.branch-code 找不到的问题,此时需要把这个往外提一层
最终 sql 给大家参考,同时感谢 v 友和 qq 好朋友的帮助。
谢谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/620280

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX