请教 SQL 写法 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ooyy
V2EX    数据库

请教 SQL 写法

  •  
  •   ooyy 2021-05-26 17:45:36 +08:00 1779 次点击
    这是一个创建于 1673 天前的主题,其中的信息可能已经有所发展或是发生改变。
    由于业务需要,要在报表中查询库存物料的历史价格,表结构如下:
    历史库存表:
    物料 年份 月份 库存
    A 2021 年 3 月 3
    A 2021 年 2 月 5
    A 2021 年 1 月 0
    A 2020 年 12 月 7
    A 2020 年 11 月 2
    A 2020 年 10 月 1
    历史成本表:
    物料 年份 月份 成本
    A 2021 年 1 月 3.22
    A 2020 年 11 月 2.68
    A 2020 年 3 月 2.55
    成本表的逻辑不是每月生成一条记录,而是当有成本变动才生成一条,没有变动不生成记录。如上表,2021 年 2 、3 、4 月的成本都是 3.22 2020 年 12 月成本是 2.68
    现在需要以左表为基础,得到物料历史月份的成本。求问大佬能否在不用存储过程的情况下用 SQL 查询实现?
    数据库是 HANA (关系型数据库),类 SQL Server,支持窗口函数
    10 条回复    2021-05-27 17:41:16 +08:00
    c6h6benzene
        1
    c6h6benzene  
       2021-05-26 18:38:35 +08:00 via iPhone
    如果有 begin month/end month 的话 join 条件可以用 between and 。没有的话只能子查询里面用 row_number 自己拼一下了?
    ooyy
        2
    ooyy  
    OP
       2021-05-26 22:32:07 +08:00
    @c6h6benzene 感谢回复,子查询的方式我考虑过,只能实现特定月份的,没办法实现所有月份的,能否再详细说一下?
    setsunakute
        3
    setsunakute  
       2021-05-27 09:35:38 +08:00
    select *, (select cost from cost where repertory.material = cost.material and repertory.year >= cost.year and repertory.month >= cost.month limit 1) as cost from repertory;


    cost 表是成本表
    repertory 是库存表
    Aksura
        4
    Aksura  
       2021-05-27 11:36:45 +08:00
    @ooyy 库存表是每个月都有值的,先用库存表 LEFT JOIN 成本表,连接条件物料相等,日期(年份和月份转换,按每月第一日算)取成本表小于等于库存表,SELECT 出每个物料最大日期,得库存表对应每月的成本值。
    c6h6benzene
        5
    c6h6benzene  
       2021-05-27 13:56:45 +08:00
    WITH costWithID AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY material ORDER BY DATEFROMPARTS(yearNo, monthNo, 1) DESC) rowNo
    , material
    , yearNo
    , monthNo
    , cost
    FROM #materials
    )
    SELECT i.*, c.cost
    FROM #inventory i
    LEFT JOIN (SELECT cur.rowNo ID
    , cur.material
    , DATEFROMPARTS(cur.yearNo, cur.monthNo, 1) BeginYearMonth
    , ISNULL(DATEADD(DAY, -1, DATEFROMPARTS(next.yearNo, next.monthNo, 1)),
    '9999-12-31') EndYearMonth
    , cur.cost
    FROM costWithID cur
    LEFT JOIN costWithID next ON cur.rowNo = next.rowNo + 1) c ON i.material = c.material
    AND DATEFROMPARTS(i.yearNo, i.monthNo, 1) BETWEEN c.BeginYearMonth AND c.EndYearMonth

    你说类似 SQL SERVER,我就按 T-SQL 来写了,希望排版不会乱掉。反正中心思想就是找出每个开始日期结束的对应日期,这样你可以根据范围来取值。
    ooyy
        6
    ooyy  
    OP
       2021-05-27 16:22:20 +08:00
    @setsunakute 感谢回复,这个方法的子查询没有办法排序,limit 1 的方式不能保证取到最近一次的成本吧?
    ooyy
        7
    ooyy  
    OP
       2021-05-27 16:26:02 +08:00
    @Aksura 感谢回复,这个方法我试了可以,用的是在左连接时候加的子查询的方式:
    select * from 库存表 d
    left join 成本表 b on d.编码 = b.编码 and b.年份&月份 = (select max(年份&月份) from 成本表 z where z.编码 = d.编码 and z.年份&月份 <= d.年份&月份)
    ooyy
        8
    ooyy  
    OP
       2021-05-27 16:27:12 +08:00
    @c6h6benzene 感谢回复,把字段转化为日期的思路很棒,感觉效率比子查询会高一些。
    setsunakute
        9
    setsunakute  
       2021-05-27 16:56:55 +08:00
    @ooyy 可以排序的, select *, (select cost from cost where repertory.material = cost.material and repertory.year >= cost.year and repertory.month >= cost.month order by cost.year desc,cost.month desc limit 1) as cost from repertory; 这样取到的就是最近时间的的成本了
    ooyy
        10
    ooyy  
    OP
       2021-05-27 17:41:16 +08:00
    @setsunakute 不知道其他数据库怎样,我使用 HANA 查询提示子查询不可使用 top 或者 order by 子句
    “correlated subquery cannot have TOP or ORDER BY”
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3943 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 05:13 PVG 13:13 LAX 21:13 JFK 00:13
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86