ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

库存账龄报表开发总结——Sqlserver LAG()的使用

2020-12-20 20:59:15  阅读:827  来源: 互联网

标签:code LAG Sqlserver stk num 账龄 goods date 2020


库存账龄报表开发总结——Sqlserver LAG()的使用

  • 开发需求

    根据出入库流水明细,查询对应产品库存状态:包含库龄、库存量及其金额等。

    注意:出库按照先入先出的规则进行。

    例如:

    物品数量日期
    A102020-01-01
    A202020-02-01
    A302020-03-03
    A-52020-04-10
    A-352020-05-15
    A3002020-06-18
    A-602020-11-10
    A902020-11-30
    A-1002020-12-12
    B202020-07-15
    B402020-10-11
    B-302020-11-11

    上面表示一个出入库流水明细

    -- 建表,并插入数据
    CREATE TABLE T_StkFlowDetail(
    	id int primary key not null,
    	goods_code varchar(20) null,
    	num decimal(16,7) null,
    	stk_date date not null
    )
    
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (1, 'A', 10.0000000, '2020-01-01');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (2, 'A', 20.0000000, '2020-02-01');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (3, 'A', 30.0000000, '2020-03-03');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (4, 'A', -5.0000000, '2020-04-10');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (5, 'A', -35.0000000, '2020-05-15');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (6, 'A', 300.0000000, '2020-06-18');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (7, 'A', -60.0000000, '2020-11-10');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (8, 'A', 90.0000000, '2020-11-30');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (9, 'A', -100.0000000, '2020-12-12');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (10, 'B', 20.0000000, '2020-07-15');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (11, 'B', 40.0000000, '2020-10-11');
    INSERT INTO [dbo].[T_StkFlowDetail]([id], [goods_code], [num], [stk_date]) VALUES (12, 'B', -30.0000000, '2020-11-11');
    

    2020-12-31为截止日期去判定最终展示报表形式

    物品库存0-60天61-120天121-180天181-240天241-300天301-360天
    A250900016000
    B300300000
  • 需求分析

    • 根据每次入库时间获取各时间段的库龄

    • 根据出库按照先入先出的规则扣减库存

    • 根据库龄将对应的库存、金额等相关数据展示

    • 综上:该报表的难度在于如何先入先出的扣减库存

  • 函数讲解

  • 解决方案

    • 查询每个物品各时间段有库存情况下的库龄
    SELECT
    	goods_code,
    	stk_date,
    	diff_days,
    	current_stk_nums,
    	current_stk_nums - ISNULL( LAG ( current_stk_nums ) OVER ( partition BY goods_code ORDER BY stk_date ), 0 ) current_stk_row_nums 
    FROM
    	(
    	SELECT
    		goods_code,
    		num,
    		stk_date,
    		DATEDIFF( DAY, stk_date, '2020-12-31' ) diff_days,
    		SUM ( CASE WHEN num < 0 THEN num ELSE 0 END ) OVER ( PARTITION BY goods_code ) + SUM ( CASE WHEN num > 0 THEN num ELSE 0 END ) OVER ( PARTITION BY goods_code ORDER BY stk_date ) current_stk_nums 
    	FROM
    		T_StkFlowDetail 
    	WHERE
    		stk_date <= '2020-12-31' 
    	) t 
    WHERE
    	current_stk_nums > 0 
    	AND num > 0
    
    • 执行结果
      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oZqM2PbZ-1608467958242)(/Users/wangzhili/Library/Application Support/typora-user-images/image-20201220201134827.png)]

    • 此处建议将上述sql写成函数,方便报表输出

      CREATE FUNCTION [dbo].[FUNC_GetStockAge] ( @end_date DATE ) RETURNS TABLE AS RETURN (
      	SELECT
      		goods_code,
      		stk_date,
      		diff_days,
      		current_stk_nums,
      		current_stk_nums - ISNULL( LAG ( current_stk_nums ) OVER ( partition BY goods_code ORDER BY stk_date ), 0 ) current_stk_row_nums 
      	FROM
      		(
      		SELECT
      			goods_code,
      			num,
      			stk_date,
      			DATEDIFF( DAY, stk_date, @end_date ) diff_days,
      			SUM ( CASE WHEN num < 0 THEN num ELSE 0 END ) OVER ( PARTITION BY goods_code ) + SUM ( CASE WHEN num > 0 THEN num ELSE 0 END ) OVER ( PARTITION BY goods_code ORDER BY stk_date ) current_stk_nums 
      		FROM
      			T_StkFlowDetail 
      		WHERE
      			stk_date <= @end_date
      		) t 
      	WHERE
      		current_stk_nums > 0 
      	AND num > 0 
      )
      
  • 报表输出语句

    SELECT 
    	t.goods_code '物品', 
    	t.num '库存',
    	SUM(IIF(t1.diff_days BETWEEN 0 AND 60,t1.current_stk_row_nums,0)) AS '0-60天',
    	SUM(IIF(t1.diff_days BETWEEN 61 AND 120,t1.current_stk_row_nums,0)) AS '61-120天',
    	SUM(IIF(t1.diff_days BETWEEN 121 AND 180,t1.current_stk_row_nums,0)) AS '121-180天',
    	SUM(IIF(t1.diff_days BETWEEN 181 AND 240,t1.current_stk_row_nums,0)) AS '181-240天',
    	SUM(IIF(t1.diff_days BETWEEN 241 AND 300,t1.current_stk_row_nums,0)) AS '241-300天',
    	SUM(IIF(t1.diff_days BETWEEN 301 AND 360,t1.current_stk_row_nums,0)) AS '301-360天'
    FROM (
    	-- 截止2020-12-31各物品的库存
    	SELECT goods_code,SUM(num) num FROM T_StkFlowDetail
    	WHERE stk_date < '2020-12-31'
    	GROUP BY goods_code
    	HAVING SUM(num) > 0 
    )t
    LEFT JOIN FUNC_GetStockAge('2020-12-31') t1 ON t1.goods_code = t.goods_code
    WHERE t.num > 0
    GROUP BY t.goods_code,t.num
    
  • 输出结果
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uBvsfWNn-1608467958243)(/Users/wangzhili/Library/Application Support/typora-user-images/image-20201220203646984.png)]

标签:code,LAG,Sqlserver,stk,num,账龄,goods,date,2020
来源: https://blog.csdn.net/weixin_43724845/article/details/111462313

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有