首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

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

  •  
  •   miv · 19 天前 · 1822 次点击

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

    24 回复  |  直到 2019-11-18 21:41:12 +08:00
        1
    miv   19 天前 via iPhone
    想上面的写法,汇总的数据会变多
    需要把广州的数据,减去广州天河某区的数据才对。
    因为匹配天河某区的数据也匹配到广州了,所以广州还要减去天河某区的数据,最后的数据才对。

    造成这个问题是,
    而且机构编码那样子。like 一下就匹配多了
        2
    miv   19 天前 via iPhone
    想问下这种机构编码的设计正常吗
    求大佬
        3
    miv   19 天前 via iPhone
    在线等
        4
    miv   19 天前 via iPhone
    出现了这个问题,然后我相关的统计代码就需要做一个剔除操作,感觉很麻烦。
    而且剔除的机构编码还是硬编码
    得在代码里面写广州需要提出广州天河某区等等
    感觉。。。
        5
    crclz   19 天前
    题目描述太少。隐隐约约感觉表 B 设计的有问题啊。

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

    这两行属于相同的业务概念?
        6
    reus   19 天前
    a 和 b 不需要关联,用子查询去取名字啊

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

    )
    from a
        7
    aguesuka   19 天前 via Android   ♥ 1
    规范的话只能用表 a 的机构编码,或者父级编码去 join 表 b 的机构编码。能提出这个问题说明数据库最好玩重新设计
        8
    reus   19 天前
    a 和 b 不需要关联,用子查询去取名字啊

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

    不记得 mysql 的函数名了,大概意思懂就行。
        9
    reus   19 天前   ♥ 1
    数据表设计没大问题,只是你想错了,从 b 表取名字要用子查询,不要用关联
        10
    YUyu101   19 天前 via Android
    所以你到底要不要天河某区,如果要的话就代码里弄,不要的话就 sql 里 join 名字不带区的第一个,如果名字也没有规则,有的要省有的要市有的要区,那这什么奇葩业务啊,硬编码吧。
        11
    miv   18 天前 via iPhone
    @reus 看不太明白,可以详细介绍吗?如果可以这样那比较好
        12
    miv   18 天前 via iPhone
    @YUyu101 需要的
        13
    miv   18 天前 via iPhone
    @crclz 嗯,有点这个意思,所以 like 天河某区就一定 like 到广州了,数据一对二重复了
        14
    miv   18 天前 via iPhone
    用的是 oracle,Java
        15
    miv   18 天前 via iPhone
    @reus 大佬意思是,a 表拿机构名字用行内子查询,like 一下,然后根据 code 长度,优先匹配机构编码长的吗
        16
    shakoon   18 天前 via Android
    a 表机构号都是 4 位的是吧?那很简单啊,select a.*, b.机构名 from a left join b on a.机构号=b.机构号 and length(b.机构号)=4
        17
    TinyKube   18 天前
    2 次查询就好了,先查 B 表需要的数据,统计 B 表的关联字段,再查询得到 A 表数据,再 Join 到 B 表
        18
    shakoon   18 天前 via Android
    哦,a 不是 4 位啊,改一下,substr(a.机构号,0,4)=b.机构号
        19
    miv   18 天前 via iPhone
    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 缺少右括号
    求助
        20
    miv   18 天前 via iPhone
    问题已解决,参考楼上老哥的方法,行内子查询。
    解决过程中遇到 2 个问题。
    1,子查询使用 order by 提示缺少右括号,需要用 select 包装一层
    2,如上面的 sql,按照 1 做法,还是出现 g.branch-code 找不到的问题,此时需要把这个往外提一层
    最终 sql 给大家参考,同时感谢 v 友和 qq 好朋友的帮助。
    谢谢
        21
    065535   17 天前   ♥ 1
    上面的方法可以解决数据查询问题,但未来可能会遇到性能瓶颈。终极建议:业务上增加一个冗余列做关联,不要用 like 了。
        22
    miv   17 天前 via iPhone
    @065535 有道理,星期天加班按那种方法搞,可以没错,性能上是一个问题,而且特别是统计业务这块,写出来 sql 我自己都绕晕了,而且很复杂。
    早知道还是用实体类分步骤去弄了。
    数据结构这方面没权力改,老哥建议很好。
        23
    lumious   17 天前   ♥ 1
    使用 b 表作为主表,对 a 表的机构编码进行截取汇总关联到主表中
    从楼主给的数据看,市一级(广州市)的编码是 4 位,区一级(白云区)的编码是 5 位
    要统计到区一级,sql 类似于这样:
    select b.地区编码,statistic.* from b,(select substr(机构编码,0,5) 地区编码,sum(业务值) group by substr(机构编码,0,5)) statistic where b.地区编码=statictic.地区编码(+) and b.地区编码 like '_____'
    这个是 oracle 的写法,mysql 改成 left join 就行
        24
    miv   17 天前
    @lumious 机构有可能是更低一级,截取不太可行.所以,今天,现在还是不考虑复杂 sql 了,今天用实体类,查询出全部数据,在一步步处理
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1035 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 28ms · UTC 20:02 · PVG 04:02 · LAX 12:02 · JFK 15:02
    ♥ Do have faith in what you're doing.