精华内容
下载资源
问答
  • 商品销售统计系统

    千次阅读 2018-11-20 13:17:32
    商品销售统计系统 问题描述:编写商品销售统计程序,商品的信息有:商品的名称,计量单位(重量或件),单价。所有商品的信息事先已存入计算机,屏幕上显示所有商品的名称,选择商品名,输入商品计量单位(如重量,...

    商品销售统计系统

    问题描述:编写商品销售统计程序,商品的信息有:商品的名称,计量单位(重量或件),单价。所有商品的信息事先已存入计算机,屏幕上显示所有商品的名称,选择商品名,输入商品计量单位(如重量,件数等),根据单价算出总价。客户一次购物可能购买多种商品,程序应计算出客户应付的钱款数。

    基本要求:程序分为两个部分:第一部分用于输入商品的信息并允许修改和删除;第二部分实现销售统计。程序运行时由用户选择使用哪一部分功能,并能在运行时在两部分之间切换。第二部分运行时,首先显示所有商品名称及代码(商品数目较多时,应考虑分屏显示),用户输入商品代码及商品重量或件数,用户一次操作可输入若干商品的购买信息,然后输入一个特殊的代码(如-1)表示本次购物结束。此时。程序计算出应付钱款数并显示。

    测试数据:程序应输入不少于10种商品的信息,并进行模拟运行。

    实现提示:本程序的商品信息管理可定义一个商品类,每种商品作为商品类的实例(对象)存储在链表节点中。

    选做内容:程序在营业结束时统计每种商品的销售量,销售金额及总营业额。因此第二部分应有营业结束的选择,当用户选择此项时屏幕上显示当天营业的每种商品的销售量,销售金额及总营业额。注意,商品类的数据成员应增加有商品的销售量和销售金额。总营业额是所有商品的营业额之和,可用静态数据成员实现。或可由原商品类派生出一个特殊的类,增加上面的数据成员及相应的成员函数。

     

    完整代码:

    #include <iostream>
    #include <string>
    #include <iomanip>    // setw()
    using namespace std;


    //全局变量
    int i=0;         //库存的商品种类量 
    char ch;           //用户输入的字符 
    int r;            //用户输入的编号 
    string code,name,unit;   //商品代码、名字、计价单位 
    double price;   //单价 
    int quantity;   //数量 


    double total;  //顾客最后结账时的总价钱 


    //ofstream f1("./test.txt");
    //ofstream f2("./sell.txt");//构建输出流


    class Commodity{     //商品类 
    private:
    string code;   //商品代码
    string name;   //商品名称 
    string unit;   //计价单位 
    double price;    //单价 
    int quantity;    //数量 

    int xsl;   //该商品销售量 
    double xsMoney;    //该商品销售金额 
    static double sumMoney;   //总营业额定义为类的静态数据成员 
    public:
    Commodity();   //无参构造函数 
    Commodity(string co,string na,string un,double pr,int qu);  //带参构造函数 
    ~Commodity();     //析构函数

    void entry();     //商品信息录入 
    void alter();      //商品信息修改 
    void del();        //商品信息删除 
    void show();       //商品信息显示 
    void stat();      //商品销售统计 
    void buy();      //商品买入 
    };
    double Commodity::sumMoney = 0;   //对静态数据域 总营业额sumMoney 进行初始化 


    Commodity::Commodity(){}
    Commodity::Commodity(string co,string na,string un,double pr,int qu){
    code = co;
    name = na;
    unit = un;
    price = pr;
    quantity = qu;
    }
    Commodity::~Commodity(){}


    Commodity *sp[100];    //对象指针数组,存放商品对象


    void Commodity::entry(){       //商品入库 
    cout<<"请选择:新品录入(1),旧品补货(2)"<<endl;
    cin>>r;
    if(r==1){
    cout<<"请输入商品代码、名称、计量单位、单价、数量(之间用空格隔开):"<<endl;
    cin>>code>>name>>unit>>price>>quantity;
    sp[i]=new Commodity(code,name,unit,price,quantity);  //创建动态对象,将地址赋值给数组中的指针 
    i++;
    cout<<"信息录入成功"<<endl;
    }
    else if(r==2){
    cout<<"请输入需要补货的商品名称:"<<endl;
    cin>>name;
    for(int k=0;k<i;k++){
    if(name==sp[k]->name){
    cout<<"该商品信息如下:"<<endl;
    cout<<"商品代码+++++++商品名称+++++++计量单位+++++++商品价格+++++++商品数量"<<endl;
    cout<<setw(15)<<left<<sp[k]->code
    <<setw(15)<<left<<sp[k]->name
    <<setw(15)<<left<<sp[k]->unit
    <<setw(15)<<left<<sp[k]->price
    <<setw(15)<<left<<sp[k]->quantity<<endl;
    cout<<"输入需入库该商品的数量:"<<endl;
    cin>>r;
    sp[k]->quantity=(sp[k]->quantity) + r;

    cout<<"补货成功!"<<endl;
    cout<<"商品代码+++++++商品名称+++++++计量单位+++++++商品价格+++++++商品数量"<<endl;
    cout<<setw(15)<<left<<sp[k]->code
    <<setw(15)<<left<<sp[k]->name
    <<setw(15)<<left<<sp[k]->unit
    <<setw(15)<<left<<sp[k]->price
    <<setw(15)<<left<<sp[k]->quantity<<endl;
    break;
    }
    else if(k==i-1)   //当遍历到最后一个还不匹配,则不存在 
    cout<<"该商品不存在,请重新确认入库类型!"<<endl;


    cout<<"是否继续入库(y or n)"<<endl;
    cin>>ch;
    if(ch=='y')
    entry();    //递归
    }


    void Commodity::alter(){      //商品信息修改 
    cout<<"请输入需修改商品的名称:"<<endl;
    cin>>name;
    for(int k=0;k<i;k++){      //遍历商品对象数组 
    if(name==sp[k]->name){
    cout<<"该商品信息如下:"<<endl;
    cout<<"商品代码+++++++商品名称+++++++计量单位+++++++商品价格+++++++商品数量"<<endl;
    cout<<setw(15)<<left<<sp[k]->code
    <<setw(15)<<left<<sp[k]->name
    <<setw(15)<<left<<sp[k]->unit
    <<setw(15)<<left<<sp[k]->price
    <<setw(15)<<left<<sp[k]->quantity<<endl;

    string ncode,nname,nunit;      //接收新的商品内容 
    double nprice;
    int nquantity;
    cout<<"输入需要修改的内容编号:代码(1)、名称(2)、计量单位(3)、单价(4)、数量(5)"<<endl;
    cin>>r;
    switch(r){
    case 1:{
    cout<<"输入商品代码:"<<endl;
    cin>>ncode;
    sp[k]->code=ncode;
    cout<<"信息修改成功!"<<endl;
    break;
    }
    case 2:{
    cout<<"输入商品名称:"<<endl;
    cin>>nname;
    sp[k]->name=nname;
    cout<<"信息修改成功!"<<endl;
    break;
    }
    case 3:{
    cout<<"输入计量单位:"<<endl;
    cin>>nunit;
    sp[k]->unit=nunit;
    cout<<"信息修改成功!"<<endl;
    break;
    }
    case 4:{
    cout<<"输入单价:"<<endl;
    cin>>nprice;
    sp[k]->price=nprice;
    cout<<"信息修改成功!"<<endl;
    break;
    }
    case 5:{
    cout<<"输入数量:"<<endl;
    cin>>nquantity;
    sp[k]->quantity=nquantity;
    cout<<"信息修改成功!"<<endl; 
    break;
    }
    }
    break;
    }
    else if(k==i-1)   //当遍历到最后一个还不匹配,则不存在 
    cout<<"该商品不存在"<<endl; 
    }
    cout<<"是否继续修改(y or n)"<<endl;
    cin>>ch;
    if(ch=='y')
    alter();    //递归
    }


    void Commodity::del(){    //信息删除 
    cout<<"输入要删除商品的名称:"<<endl;
    cin>>name;
    for(int k=0;k<i;k++){
    if(name==sp[k]->name){
    for(int h=k;h<i;h++){  //将删除位置后面的所有商品对象向前移动一个位置 
    sp[h]=sp[h+1];   //指针指向地址复制给前一个指针所指地址 
    }
    i--;
    delete sp[i];// 释放内存 
    cout<<"信息删除成功!"<<endl;
    break;
    }
    else if(k==i-1)   当遍历到最后一个还不匹配,则不存在 
    cout<<"该商品不存在,无法进行删除操作!"<<endl;
    }
    cout<<"是否继续(y or n)"<<endl;
    cin>>ch;
    if(ch=='y')
    del();
    }


    void Commodity::show(){      //信息显示 
    cout<<"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl; 
    cout<<"+----------------------所有商品信息----------------------+"<<endl; 
    cout<<"=========================================================="<<endl; 
    cout<<"商品代码+++++++商品名称+++++++计量单位+++++++商品价格+++++++商品数量"<<endl; 

    if(i==0)
    cout<<"无可显示的商品信息!"<<endl;
    for(int k=0;k<i;k++){
    cout<<setw(15)<<left<<sp[k]->code
    <<setw(15)<<left<<sp[k]->name
    <<setw(15)<<left<<sp[k]->unit
    <<setw(15)<<left<<sp[k]->price
    <<setw(15)<<left<<sp[k]->quantity<<endl; 
    }
    }


    void Commodity::stat(){     //商品销售统计 
    for(int k=0;k<i;k++){
    cout<<sp[k]->name<<"的销售量和销售金额分别为:"<<endl;
    cout<<sp[k]->xsl<<sp[k]->unit<<"!  "
    <<sp[k]->xsMoney<<"元!"<<endl;
    sumMoney += sp[k]->xsMoney;
    }
    cout<<"总营业额为:"<<sumMoney<<endl;



    void Commodity::buy(){                  //商品出售 
    double numPr;//一种商品的总价
    cout<<"输入顾客要购买的商品名称:"<<endl;
    cin>>name;
    for(int k=0;k<i;k++){  //遍历所有商品,查找有没有货 
    if(name==sp[k]->name){
    cout<<"输入购买数量:"<<endl;
    cin>>quantity;

    sp[k]->xsl +=quantity;     //该商品的销售量累加 
    numPr=quantity*sp[k]->price; 
    sp[k]->xsMoney +=numPr;     //该商品的销售金额累加 
     
    sp[k]->quantity-=quantity;   //商店剩下的商品减少
    total+=numPr;  //顾客总账累加 

    cout<<"商品代码+++++++商品名称+++++++计量单位+++++++商品价格+++++++商品数量+++++++小计"<<endl;
    cout<<setw(15)<<left<<sp[k]->code
    <<setw(15)<<left<<sp[k]->name
    <<setw(15)<<left<<sp[k]->unit
    <<setw(15)<<left<<sp[k]->price
    <<setw(15)<<left<<sp[k]->quantity
    <<setw(15)<<left<<numPr<<endl;  
    cout<<"购买成功!"<<endl;
    break;
    }


    cout<<"是否继续购买(y or n)"<<endl;
    cin>>ch;
    if(ch=='y')
    buy();
    else{
    cout<<"购买结束!总共消费:"<<total<<" 元!"<<endl;
    cout<<"营业是否结束?(y or n)"<<endl;
    cin>>ch;
    if(ch=='y')
    stat(); 
    }
    }


    void cd1(){  //信息管理菜单 
    Commodity sp; //  无参构造函数创建命名对象 
    cout<<"+++++++++++++++++++++++++商品信息管理++++++++++++++++++++++++"<<endl;
    cout<<"+   录入信息(1)    修改信息(2)    删除信息(3)    返回(4)    +"<<endl; 
    cout<<"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"<<endl;
    cout<<"请选择:"<<endl;
    cin>>r;
    switch(r){
    case 1:
    sp.entry();
    if(ch=='n')   //  entry()最后选择不继续 n,则返回cd1() 
    cd1();
    break;
    case 2:
    sp.alter();
    if(ch=='n')
    cd1();
    break;
    case 3:
    sp.del();
    if(ch=='n')
    cd1();
    break;
    }  
    }


    void cd2(){    //销售菜单 
      Commodity sp;
      sp.show();  //展示所有商品,供选择 
    cout<<endl; 
      sp.buy();   //开买 
      if(ch=='n')   //若在 buy()中不结束营业,则回到销售菜单 
      cd1();
    }


    void cd(){    //总菜单
    cout<<"***************************************************"<<endl; 
    cout<<"*                                                 *"<<endl;
        cout<<"*------------欢迎进入商品销售统计系统-------------*"<<endl;
        cout<<"*                                                 *"<<endl;
        cout<<"***************************************************"<<endl; 
        
        cout<<"请选择您的操作:商品信息管理系统(1)商品销售系统(2)"<<endl;
        cin>>ch;
        if(ch=='1'){
        cd1();
        if(r==4)  //对应操作 信息管理菜单中的 返回(4) 
        cd();
    }
    else if(ch=='2'){
    cd2();    //进入销售菜单 
    }
    else{
    cout<<"输入错误,请重新输入!"<<endl;
    cd();   //递归返回总菜单 
    }
    }


    int main(){
    cd();
    return 0;

     

    展开全文
  • IMS-进销存管理系统基于 Java 实现的进销存管理系统(Inventory Management System)项目结构系统功能设计进货管理(Stock-In)进货入库(StockIn):Btn->Form入库记录(StockInRecord):Table销售管理(Stock-Out)销售...

    IMS-进销存管理系统

    基于 Java 实现的进销存管理系统(Inventory Management System)

    项目结构

    f0dc4f15c4d59d2fab7c397d06b22157.png

    系统功能设计

    进货管理(Stock-In)

    进货入库(StockIn):Btn->Form

    入库记录(StockInRecord):Table

    销售管理(Stock-Out)

    销售出库(StockOut):Btn->Form

    出库记录(StockOutRecord):Table

    库存管理(Inventory )

    查询库存(Inventory):Table

    商品管理(InventoryMng):Btn->Form

    统计报表(Statistics)

    商品采购统计(StatisticsStockIn):统计图

    商品销售统计(StatisticsStockOut):统计图

    MVC项目架构

    Model:数据模型层

    View:视图层

    Controller:控制层

    View:UI层

    Controller:控制层

    Service:业务逻辑

    DAO:底层实现

    DB:数据库

    GUI设计

    .

    |—— 用户登陆界面(LoginFrame)

    |—— 主界面(MainFrame)

    |—— 菜单栏(MenuPanel):logo,进货管理,销售出库,库存管理,统计报表

    |—— 内容栏(ContentPanel)

    |—— 进货管理(StockInPanel):入库记录(StockInRecordTable),进货入库(StockInBtn->Form)

    |—— 销售管理(StockOutPanel):出库记录(StockOutRecordTable),销售出库(StockOutBtn->Form)

    |—— 库存管理(InventoryPanel):查询库存(InventoryTable),商品管理(InventoryMngBtn->Form)

    |—— 统计报表(StatisticsPanel):采购统计,销售统计

    数据库设计

    用户表user:id (uk),username,md5(password);

    库存表product:proId (uk),proName,dirName,supplier,brand,count;

    记录表record:date,proId,proName,count,register,recordType;

    功能实现

    1. 进货管理(Stock-In):

    入库记录表(StockInRecord):查询by日期/产品名称/分类;

    进货入库(StockIn):

    if(新商品在product表中存在){

    商品库存量 += count;

    }else{

    插入新商品到product表中;

    }

    插入一条入库记录到record表中

    2. 销售出库(Stock-Out):

    出库记录表(StockInRecord):查询by日期/产品名称/分类;

    销售出库(StockOut):

    if(新商品在product表中存在){

    if(被删除商品的库存数量>出库数量){

    商品库存量 -= count;

    }else{

    提示商品库存不足;

    }

    }else{

    商品不存在

    }

    3. 库存管理(Inventory )

    查询库存(Inventory):查询by产品名称/库存范围/分类;

    商品管理(InventoryMng):

    选中库存表中任意一行

    Mng.product = 获取到改行的product对象;

    if(选中的product不为空){

    修改商品信息;

    更新product表信息;

    更新record表信息;

    }

    4. 统计报表(Statistics)

    JFreeChart生成统计图。

    5. 数据导入导出

    基于Apache POI实现的表格数据导出为Excel.xlsx表格。

    还想实现的功能

    手机验证码,邮箱验证码。

    验证码验证,滑块验证,文字验证。

    时间戳随机生成订单序号。

    多角色使用。

    多终端使用。

    全部检索。

    伪删:触发器

    总结

    编写开发手册,需求分析+系统设计。

    编写开发手册,统一命名规则。

    合作沟通是提升效率的关键。

    展开全文
  • jsp商品销售管理系统

    2012-05-18 14:15:33
    系统设计与论文,商品在线销售管理系统系统功能有交易管理、进货统计管理、销售统计管理、 员工销售业绩考核等。系统的主要模块有:用户功能模块,系统交易模块,数据库查看模块,后台管理模块等。
  • 塑料卡板销售统计管理系统是一款对商品销售情况进行统一管理的系统。 程序特点1,简单,方便,网络操作,不受单台电脑文件保存限制2,纸质与数据库客户数据保存,查询变得更为方便3,免去久远的历史单据与数据查询烦恼4...
  • 商品销售管理系统

    2006-03-16 00:00:00
    商品销售管理系统》用于商业公司的商品的销售管理,用于管理商品报价单、客户商品订单、商品的销售单及客户的商品退货单,可按日、月、季、年统计商品的销售数量及销售金额,按月、季、年统计客户的退货数量及退货...
  • C#商品销售管理系统

    2011-05-05 09:08:03
    C#+sql2000的销售管理系统 1、概述 1 2、需求分析 2 ...5.1商品销售管理系统各子系统构成 15 5.2 商品管理 16 5.3统计查询 16 6、系统功能模块图 17 6.1系统设计 17 6.1.1系统功能描述以及设置思路 17
  • 商品销售系统

    2006-03-16 00:00:00
    对商品的划价管理,销售管理,打印库存单,销售单,商品销售统计和打印统计(包含日结统计和月结统计),一般的进销存软件无法比拟,此软件操作很简单,按照平常人的思维而进行开发的,只要懂得电脑一般都可以在短时间学会,本...
  • 商品销售管理系统主要是对商品基础信息、商品入库信息、商品销售信息和商品退货信息进行管理,同时提供对商品销售统计的功能。另外,系统还增添客户信息、供应商信息等基础信息模块。项目实施后,能够增强企业信息...
  • 系统编写使用C++编写,开发软件为QT 5.9;目的是实现一个小型的超市管理系统,具有入库、出库、利润统计销售等功能
  • 星宇商品销售管理系统,适合中小门店商品销售收银等场所的批发零售,操作简单,功能实用。软件支持小票打印机、商品条形码扫描、顾客显示屏、钱箱功能,使用该软件可以方便地进行进、销、存等商品销售管理、会员积分...
  • 能对每天销售商品进行统计汇总。 生成日报表,月报表,库存统计报表
  • 易用商品销售管理系统是一款简单好用的商品销售管理系统软件。软件以业务为基础,集进货、销售、库存、财务功能为一体,特别适合中小企业管理人员使用,能够实现包括采购入库、采购退货、销售出库、销售退货、POS...
  • 4、营业分析:商品销售统计排行、客户消费统计、业务人员业绩统计操作、营业历程对比、营业综合分析等多项统计功能并有相应的图表显示。 5、可根据供货商信息查询库存信息及销售信息。 6、日常费用登记查询。 7、...
  • VS2005商品销售系统

    2010-05-04 10:55:58
    商品销售信息管理系统的总目标是在计算机网络和数据库的先进开发平台上利用现有的软件配置一定的硬件,开发一个具有开放体系结构的、易扩充的、易维护的、具有良好的人机交互界面的商品销售信息管理,实现商店业务的...
  • 一个用C#开发的鞋类商品销售系统,WinForm程序。 提供了销售管理、库存管理、简单的数据统计以及系统管理等功能。 系统用户:老板, 密码:123456 技术交流请联系开发团队 开发团队联系方式系统内提供! 由于上传...
  • 查询统计主要包括:商品进货查询、进货退货查询、商品销售查询、销售退货查询、商品库存查询、商品销售排行。其中商品进货查询、进货退货查询、商品销售查询、销售退货查询、商品库存查询的操作方法相同,下面以...
  • 4、营业分析:商品销售统计排行、客户消费统计、业务人员业绩统计操作、营业历程对比、营业综合分析等多项统计功能并有相应的图表显示。 5、可根据供货商信息查询库存信息及销售信息。 6、日常费用登记查询。 7、...
  • 商品房销售管理系统Delphi程序源码,售楼系统,功能模块主要有:销售报表、打英预销售查询、楼盘表查询、销售统计、违约查询、报表预览、销售历史查询、系统设置、数据设定等,界面和功能都挺实用,使用的三方也不多...
  • 包括供应商管理,商品和库存管理,以及顾客管理三部分。面向的用户分为商店店员和顾客。可进行信息编辑、增加、修改、撤销和确认、统计。还有背景音乐等代码!!
  • C#商品销售系统详细设计报告

    千次阅读 2018-09-28 18:12:40
    C#商品销售系统详细设计报告 开发背景 学校要求学生进行实践练习,以此系统作为软件开发练习十分合适 编写目的 首先这份报告是根据商品销售系统需求分析报告、产品概要设计报告和软件产品数据库设计...

    C#商品销售系统详细设计报告

    • 开发背景
      学校要求学生进行实践练习,以此系统作为软件开发练习十分合适

    • 编写目的

    • 首先这份报告是根据商品销售系统需求分析报告、产品概要设计报告和软件产品数据库设计说明书所编写的。随着时代的进步,小店业务的扩展,为方便店主对本店进货,数据统计,出售,备份恢复数据,以及商品的管理,开发本系统,最终将达成小店所有信息都由此系统储存,计算并管理的效果。

    • 开发工具

    • SQL Serve2012
      SQL Server是一个可扩展的、高性能的、为分布式客户机/服务器计算所设计的数据库管理系统,实现了与WindowsNT的有机结合,提供了基于事务的企业级信息管理系统方案。SQL语句可以用来执行各种各样的操作,例如更新数据库中的数据,从数据库中提取数据等。目前,绝大多数流行的关系型数据库管理系统,如Oracle,Sybase,Microsoft SQL Server,Access等都采用了SQL语言标准。虽然很多数据库都对SQL语句进行了再开发和扩展,但是包括Select,Insert,Update,Delete,Create,以及Drop在内的标准的SQL命令仍然可以被用来完成几乎所有的数据库操作。

    • Microsoft Visual Studio2010
      Microsoft Visual Studio(简称VS)是美国微软公司的开发工具包系列产品。VS是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具、代码管控工具、集成开发环境(IDE)等等。所写的目标代码适用于微软支持的所有平台,包括Microsoft Windows、Windows Mobile、Windows CE、.NET Framework、.NET Compact Framework和Microsoft Silverlight 及Windows Phone。
      Visual Studio是目前最流行的Windows平台应用程序的集成开发环境。最新版本为 Visual Studio 2017 版本,基于.NET Framework 4.5.2 。

    • 系统需求
      本系统的功能主要分为用户登录,进货管理,销售管理,备份功能,库存管理等。各个功能模块之间既独立又相互联系,系统功能总图如下:
      在这里插入图片描述

    • 系统运行环境
      运行环境:机型;华为飞行堡垒
      主频;1.1GHz
      内存容量;8GB
      磁盘容量;1000GB,固态硬盘
      特殊部件;CPU为英特尔M5
      CPU:英特尔i5-3.5GHZ
      内存:8G以上
      硬盘:500G
      操作系统:Windows 10
      开发工具:Visual Studio 2010
      数据库:SQL Serve数据库

    • 系统架构设计
      如下图表所示的建立系统的架构设计模型。业务层逻辑、用户界面层、数据访问层为系统所分成的三层对象分层。如图所示:
      在这里插入图片描述
      数据访问层负责对数据库进行数据的增删查改,数据访问是用户访问数据的方式。首先针对数据结构层,划分了数据库以及配置配置文件来呈现这一层的数据支持。
      接下来用户界面针对系统管理员以及合法操作、普通用户的界面展示了系统初始化和主菜单显示。其中合法事务包括身份验证和操作验证,这个环节很重要也对以下供应商等管理有明确分配。
      第三层业务逻辑层是软件的系统管理总概括,包括系统系统常规功能、员工管理、供应商管理、商品管理、库存管理、进货管理、销售管理和销售数据管理
      第四层数据访问层,包括仔细的功能呢模块:系统用户管理、系统数据安全性管理、系统易用性管理、员工管理(增删查改)、库存查询、库存报警、商品进货、进货单管理、销售数据查询和销售数据统计。

    • E-R图

    在这里插入图片描述

    • 系统数据库(DB_GoodSale)设计
      在这里插入图片描述

    本文并未写出全部的系统详细设计报告内容,此文仅作为作者个人学习记录,供大家参考交流,未经许可不得转载。

    展开全文
  • 主要包括基础信息管理,日常业务管理,查询统计管理,系统信息管理等模块!
  • 实时统计每天pv,uv的sparkStreaming结合redis结果存入mysql供前端展示 https://blog.csdn.net/ddxygq/article/details/81258643 Flume+Kafka+Storm+Redis构建大数据实时处理系统:实...

    https://blog.csdn.net/m0_37739193/article/details/74559826

    实时统计每天pv,uv的sparkStreaming结合redis结果存入mysql供前端展示

    https://blog.csdn.net/ddxygq/article/details/81258643

    Flume+Kafka+Storm+Redis构建大数据实时处理系统:实时统计网站PV、UV+展示

    flume+kafka+slipstream实现黑名单用户访问实时监测

    实战SparkStream+Kafka+Redis实时计算商品销售额https://blog.csdn.net/whzhaochao/article/details/77717660

    spark streaming从kafka获取数据,计算处理后存储到redis

    https://blog.csdn.net/qq_26222859/article/details/79301205 

    大数据采集、清洗、处理:使用MapReduce进行离线数据分析完整案例https://blog.51cto.com/xpleaf/2095836

     

    一、大数据处理的常用方法、项目的流程:

    大数据采集、清洗、处理:使用MapReduce进行离线数据分析完整案例

    在互联网应用中,不管是哪一种处理方式,其基本的数据来源都是日志数据,例如对于web应用来说,则可能是用户的访问日志、用户的点击日志等。

    大数据处理目前比较流行的是两种方法,一种是离线处理,一种是在线处理,基本处理架构如下:

    当然,如果只是希望得到数据的分析结果,对处理的时间要求不严格,就可以采用离线处理的方式,比如我们可以先将日志数据采集到HDFS中,之后再进一步使用MapReduce、Hive等来对数据进行分析,这也是可行的。 

     

    • Flume将网站日志数据采集到HDFS分布式存储系统中
    • Spark SQL清洗存储在HDFS的网站日志数据,清洗完后将其数据继续存储在HDFS中
    • Hive建立数据仓库,建立外部表,将清洗完的日志数据从HDFS中导入到Hive的外部表中,作为基础数据的存储
    • 在Hive中新建新的外部表用于存储PV、UV的结果数据
    • 用Hive的HQL统计分析日志数据,统计出PV、UV并将结果数据存到新的外部表中
    • 将统计完的PV、UV数据使用Sqoop从Hive同步到外部的MySQL中供给WEB前端使用

    如果对于数据的分析结果在时间上有比较严格的要求,则可以采用在线处理的方式来对数据进行分析,如使用Spark、flink等进行处理。比较贴切的一个例子是天猫双十一的成交额,在其展板上,我们看到交易额是实时动态进行更新的,对于这种情况,则需要采用在线处理。

    • 如何一步步构建我们的实时处理系统(Flume+Kafka+Storm+Redis)
    • 1.Flume将网站日志数据采集到kafka、
    • 2.sparkstreaming实时处理kafka数据网站的用户访问日志,并统计出该网站的PV、UV
    • 3.将实时分析出的PV、UV等指标,实时处理后发送kafka+node.js展示
    • 动态地展示在我们的前面页面上

    本文主要分享对某个电商网站产生的用户访问日志(access.log)进行离线处理与分析的过程,基于MapReduce的处理方式,最后会统计出某一天不同省份访问该网站的uv与pv。

    1 、数据源

    在我们的场景中,Web应用的部署是如下的架构:

    即比较典型的Nginx负载均衡+KeepAlive高可用集群架构,在每台Web服务器上,都会产生用户的访问日志,业务需求方给出的日志格式如下:

    1001    211.167.248.22  eecf0780-2578-4d77-a8d6-e2225e8b9169    40604   1       GET /top HTTP/1.0       408     null      null    1523188122767
    1003    222.68.207.11   eecf0780-2578-4d77-a8d6-e2225e8b9169    20202   1       GET /tologin HTTP/1.1   504     null      Mozilla/5.0 (Windows; U; Windows NT 5.1)Gecko/20070309 Firefox/2.0.0.3  1523188123267
    1001    61.53.137.50    c3966af9-8a43-4bda-b58c-c11525ca367b    0       1       GET /update/pass HTTP/1.0       302       null    null    1523188123768
    1000    221.195.40.145  1aa3b538-2f55-4cd7-9f46-6364fdd1e487    0       0       GET /user/add HTTP/1.1  200     null      Mozilla/4.0 (compatible; MSIE 7.0; Windows NT5.2)       1523188124269
    1000    121.11.87.171   8b0ea90a-77a5-4034-99ed-403c800263dd    20202   1       GET /top HTTP/1.0       408     null      Mozilla/5.0 (Windows; U; Windows NT 5.1)Gecko/20070803 Firefox/1.5.0.12 1523188120263
    
    appid   ip  mid   userid   login_type   request   status   http_referer   user_agent  time
    其中:
    appid包括 : web:1000,android:1001,ios:1002,ipad:1003
    mid:         唯一的id此id第一次会种在浏览器的cookie里。如果存在则不再种。作为浏览器唯一标示。移动端或者pad直接取机器码。
    login_type: 登录状态,0未登录、1:登录用户
    request:    类似于此种 "GET /userList HTTP/1.1"
    status:     请求的状态主要有:200 ok、404 not found、408 Request Timeout、500 Internal Server Error、504 Gateway Timeout等
    http_referer:请求该url的上一个url地址。
    user_agent:  浏览器的信息,例如:"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"
    time:       时间的long格式:1451451433818。

    如果备份日志或者日志切割:
    vim /opt/cut_nginx.sh

    #!/bin/bash
    #切割日志
    datetime=$(date -d "-1 day" "+%Y%m%d")
    log_path="/usr/local/nginx/logs" 
    pid_path="/usr/local/nginx/logs/nginx.pid" 
    [ -d $log_path/backup ] || mkdir -p $log_path/backup 
    if [ -f $pid_path ] 
    then 
    mv $log_path/access.log $log_path/backup/access.log-$datetime 
    kill -USR1 $(cat $pid_path) 
    find $log_path/backup -mtime +30 | xargs rm -f
     #mtime :文件被修改时间 atime:访问时间(文件中的数据库最后被访问的时间) ctime:改变时间(文件的元数据发生变化。比如权限,所有者等)
    else 
    echo "Error,Nginx is not working!" | tee -a /var/log/messages 
    fi

    chmod +x /opt/cut_nginx.sh

    crontab -e 设置定时任务

    0  0  *  *  *     /opt/cut_nginx.sh

    1、模拟生成实时数据

    public class SimulateData {
        public static void main(String[] args) {
            BufferedWriter bw = null;
            try {
                bw = new BufferedWriter(new FileWriter("G:\\Scala\\实时统计每日的品类的点击次数\\data.txt"));
                int i = 0;
                while (i < 20000){
                    long time = System.currentTimeMillis();
                    int categoryid = new Random().nextInt(23);
                    bw.write("ver=1&en=e_pv&pl=website&sdk=js&b_rst=1920*1080&u_ud=12GH4079-223E-4A57-AC60-C1A04D8F7A2F&l=zh-CN&u_sd=8E9559B3-DA35-44E1-AC98-85EB37D1F263&c_time="+time+"&p_url=http://list.iqiyi.com/www/"+categoryid+"/---.html");
                    bw.newLine();
                    i++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    } 
    /*
    ver=1&en=e_pv&pl=website&sdk=js&b_rst=1920*1080&u_ud=12GH4079-223E-4A57-AC60-C1A04D8F7A2F&l=zh-CN&u_sd=8E9559B3-DA35-44E1-AC98-85EB37D1F263&c_time=1526975174569&p_url=http://list.iqiyi.com/www/9/---.html
    ver=1&en=e_pv&pl=website&sdk=js&b_rst=1920*1080&u_ud=12GH4079-223E-4A57-AC60-C1A04D8F7A2F&l=zh-CN&u_sd=8E9559B3-DA35-44E1-AC98-85EB37D1F263&c_time=1526975174570&p_url=http://list.iqiyi.com/www/4/---.html
    ver=1&en=e_pv&pl=website&sdk=js&b_rst=1920*1080&u_ud=12GH4079-223E-4A57-AC60-C1A04D8F7A2F&l=zh-CN&u_sd=8E9559B3-DA35-44E1-AC98-85EB37D1F263&c_time=1526975174570&p_url=http://list.iqiyi.com/www/10/---.html
     */

    模拟数据实时的写入data.log:需要一直启动着:

    #!/bin/bash
    cat demo.csv | while read line
    do 
    echo "$line" >> data.log
    sleep 1
    done

     或者生成数据直接发送kafka

    
    /**
     * 这里产生数据,就会发送给kafka,kafka那边启动消费者,就会接收到数据,这一步是用来测试生成数据和消费数据没有问题的,确定没问题后要关闭消费者,
     * 启动OnlineBBSUserLogss.java的类作为消费者,就会按pv,uv等方式处理这些数据。
     * 因为一个topic只能有一个消费者,所以启动程序前必须关闭kafka方式启动的消费者(我这里没有关闭关闭kafka方式启动的消费者也没正常啊) 
     */
    public class SparkStreamingDataManuallyProducerForKafkas extends Thread{
    	
    	//具体的论坛频道
    	static String[] channelNames = new  String[]{
    		"Spark","Scala","Kafka","Flink","Hadoop","Storm",
    		"Hive","Impala","HBase","ML"
    	};
    	//用户的两种行为模式
    	static String[] actionNames = new String[]{"View", "Register"};
    	private static Producer<String, String> producerForKafka;
    	private static String dateToday;
    	private static Random random;
    	
    	//2、作为线程而言,要复写run方法,先写业务逻辑,再写控制
    	@Override
    	public void run() {
    		int counter = 0;//搞500条
    		while(true){//模拟实际情况,不断循环,异步过程,不可能是同步过程
    		   counter++;
    		  String userLog = userlogs();
    		  System.out.println("product:"+userLog);
    		  //"test"为topic
    		  producerForKafka.send(new KeyedMessage<String, String>("test", userLog));
    		  if(0 == counter%500){
    				counter = 0;
    				try {
    				   Thread.sleep(1000);
    				} catch (InterruptedException e) {
    				   // TODO Auto-generated catch block
    				   e.printStackTrace();
    				}
    			}
    		}
    	}
    		
    	private static String userlogs() {
    		StringBuffer userLogBuffer = new StringBuffer("");
    		int[] unregisteredUsers = new int[]{1, 2, 3, 4, 5, 6, 7, 8};
    		long timestamp = new Date().getTime();
    			Long userID = 0L;
    			long pageID = 0L;
    			//随机生成的用户ID 
    			if(unregisteredUsers[random.nextInt(8)] == 1) {
    			   userID = null;
    			} else {
    			   userID = (long) random.nextInt((int) 2000);
    			}
    			//随机生成的页面ID
    			pageID =  random.nextInt((int) 2000);          
    			//随机生成Channel
    			String channel = channelNames[random.nextInt(10)];
    			//随机生成action行为
    			String action = actionNames[random.nextInt(2)];
    			
    			userLogBuffer.append(dateToday)
    						.append("\t")
    						.append(timestamp)
    						.append("\t")
    						.append(userID)
    						.append("\t")
    						.append(pageID)
    						.append("\t")
    						.append(channel)
    						.append("\t")
    						.append(action);   //这里不要加\n换行符,因为kafka自己会换行,再append一个换行符,消费者那边就会处理不出数据
    		return userLogBuffer.toString();
    	}
        
    	public static void main(String[] args) throws Exception {
    	  dateToday = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
    	  random = new Random();
    		Properties props = new Properties();
    		props.put("zk.connect", "h71:2181,h72:2181,h73:2181");
    		props.put("metadata.broker.list","h71:9092,h72:9092,h73:9092");
    		props.put("serializer.class", "kafka.serializer.StringEncoder");
    		ProducerConfig config = new ProducerConfig(props);
    		producerForKafka = new Producer<String, String>(config);
    		new SparkStreamingDataManuallyProducerForKafkas().start(); 
    	}
    } 
    
    /**
    product:2017-06-20      1497948113827   633     1345    Hive    View
    product:2017-06-20      1497948113828   957     1381    Hadoop  Register
    product:2017-06-20      1497948113831   300     1781    Spark   View
    product:2017-06-20      1497948113832   1244    1076    Hadoop  Register
    **/

    2、数据采集:获取原生数据

    数据采集工作:使用Flume对于用户访问日志的采集,将采集的数据保存到HDFS中 (离线)、发送数据到kafka(实时)

    2、flume发送数据到kafka

    从data.log文件中读取实时数据到kafka:

    第一步:配置Flume文件:(file2kafka.properties)

    a1.sources = r1
    a1.sinks = k1
    a1.channels =c1
    
    a1.sources.r1.type = exec
    a1.sources.r1.command = tail -F /home/hadoop/data.log
    
    a1.channel.c1 = memory
    
    a1.sinks.k1.type = org.apache.flume.sink.kafka.KafkaSink
    a1.sinks.k1.topic = aura
    a1.sinks.k1.brokerList = hodoop02:9092
    a1.sinks.k1.requiredAcks = 1
    a1.sinks.k1.batchSize = 5
    
    a1.sources.r1.channels = c1
    a1.sinks.k1.channel = c1

    第四步:启动Flume命令

    [hadoop@hadoop02 apache-flume-1.8.0-bin]$

    bin/flume-ng agent --conf conf --conf-file /usr/local/flume/example/file2kafka.properties --name a1 -Dflume.root.logger=INFO,console 
     

    第三步:启动kafka消费者

    [hadoop@hadoop03 kafka_2.11-1.0.0]$

    bin/kafka-console-consumer.sh --zookeeper hadoop:2181 --from-beginning --topic aura

    4 数据清洗:将不规整数据转化为规整数据(存入hdfs或者hive用于离线分析统计)

    4.3.3 执行MapReduce程序

    将上面的mr程序打包后上传到我们的Hadoop环境中,这里,对2018-04-08这一天产生的日志数据进行清洗,执行如下命令:

    yarn jar data-extract-clean-analysis-1.0-SNAPSHOT-jar-with-dependencies.jar\
    cn.xpleaf.dataClean.mr.job.AccessLogCleanJob \
    hdfs://ns1/input/data-clean/access/2018/04/08 \
    hdfs://ns1/output/data-clean/access

    5 数据处理:对规整数据进行统计分析

     

     

     

    6、Kafka消费者,SparkStream时实计算商品销售额--redis

    http://blog.csdn.net/whzhaochao/article/details/77717660

    object OrderConsumer {
      //Redis配置
      val dbIndex = 0
      //每件商品总销售额
      val orderTotalKey = "app::order::total"
      //每件商品上一分钟销售额
      val oneMinTotalKey = "app::order::product"
      //总销售额
      val totalKey = "app::order::all"
    
      def main(args: Array[String]): Unit = {
    
        // 创建 StreamingContext 时间片为1秒
        val conf = new SparkConf().setMaster("local").setAppName("UserClickCountStat")
        val ssc = new StreamingContext(conf, Seconds(1))
    
        // Kafka 配置
        val topics = Set("order")
        val brokers = "127.0.0.1:9092"
        val kafkaParams = Map[String, String](
          "metadata.broker.list" -> brokers,
          "serializer.class" -> "kafka.serializer.StringEncoder")
    
        // 创建一个 direct stream
        val kafkaStream = KafkaUtils.createDirectStream[String, String, StringDecoder, StringDecoder](ssc, kafkaParams, topics)
    
        //解析JSON
        val events = kafkaStream.flatMap(line => Some(JSON.parseObject(line._2)))
    
        // 按ID分组统计个数与价格总合
        val orders = events.map(x => (x.getString("id"), x.getLong("price"))).groupByKey().map(x => (x._1, x._2.size, x._2.reduceLeft(_ + _)))
    
        //输出
        orders.foreachRDD(x =>
          x.foreachPartition(partition =>
            partition.foreach(x => {
    
              println("id=" + x._1 + " count=" + x._2 + " price=" + x._3)
    
              //保存到Redis中
              val jedis = RedisClient.pool.getResource
              jedis.select(dbIndex)
              //每个商品销售额累加
              jedis.hincrBy(orderTotalKey, x._1, x._3)
              //上一分钟第每个商品销售额
              jedis.hset(oneMinTotalKey, x._1.toString, x._3.toString)
              //总销售额累加
              jedis.incrBy(totalKey, x._3)
              RedisClient.pool.returnResource(jedis)
            })
          ))
    
        ssc.start()
        ssc.awaitTermination()
      }
    } 
    /*
    id=4 count=3 price=7208
    id=8 count=2 price=10152
    id=7 count=1 price=6928
    id=5 count=1 price=3327
    id=6 count=3 price=20483
    id=0 count=2 price=9882
    */

    Redis客户端

    object RedisClient extends Serializable {
      val redisHost = "127.0.0.1"
      val redisPort = 6379
      val redisTimeout = 30000
      lazy val pool = new JedisPool(new GenericObjectPoolConfig(), redisHost, redisPort, redisTimeout)
    
      lazy val hook = new Thread {
        override def run = {
          println("Execute hook thread: " + this)
          pool.destroy()
        }
      }
      sys.addShutdownHook(hook.run)
      def main(args: Array[String]): Unit = {
        val dbIndex = 0
        val jedis = RedisClient.pool.getResource
        jedis.select(dbIndex)
        jedis.set("test", "1")
        println(jedis.get("test"))
        RedisClient.pool.returnResource(jedis)
      }
    }
    

     

    DAU日活 

      // 转换处理
        val startuplogStream: DStream[Startuplog] = inputDstream.map {
          record =>
            val jsonStr: String = record.value()
            val startuplog: Startuplog = JSON.parseObject(jsonStr, classOf[Startuplog])
            val date = new Date(startuplog.ts)
            val dateStr: String = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date)
            val dateArr: Array[String] = dateStr.split(" ")
            startuplog.logDate = dateArr(0)
            startuplog.logHour = dateArr(1).split(":")(0)
            startuplog.logHourMinute = dateArr(1)
    
            startuplog
        }
        // 利用redis进行去重过滤
        val filteredDstream: DStream[Startuplog] = startuplogStream.transform {
          rdd =>
            println("过滤前:" + rdd.count())
            //driver  //周期性执行DataFrame
            val curdate: String = new SimpleDateFormat("yyyy-MM-dd").format(new Date)
            val jedis: Jedis = RedisUtil.getJedisClient
            val key = "dau:" + curdate
            val dauSet: util.Set[String] = jedis.smembers(key) //SMEMBERS key 获取集合里面的所有key
          val dauBC: Broadcast[util.Set[String]] = ssc.sparkContext.broadcast(dauSet)
            val filteredRDD: RDD[Startuplog] = rdd.filter {
              startuplog =>
                //executor
                val dauSet: util.Set[String] = dauBC.value
                !dauSet.contains(startuplog.mid)
            }
            println("过滤后:" + filteredRDD.count())
            filteredRDD
    
        }
    
        //去重思路;把相同的mid的数据分成一组 ,每组取第一个
        val groupbyMidDstream: DStream[(String, Iterable[Startuplog])] = filteredDstream
          .map(startuplog => (startuplog.mid, startuplog))
          .groupByKey()
    
        val distinctDstream: DStream[Startuplog] = groupbyMidDstream.flatMap {
          case (mid, startulogItr) =>
            startulogItr.take(1)
        }
    
    
        // 保存到redis中
        distinctDstream.foreachRDD { rdd =>
          // redis  type set
          // key  dau:2019-06-03    value : mids
          rdd.foreachPartition { startuplogItr =>
            //executor
            val jedis: Jedis = RedisUtil.getJedisClient
            val list: List[Startuplog] = startuplogItr.toList
            for (startuplog <- list) {
              val key = "dau:" + startuplog.logDate
              val value = startuplog.mid
              jedis.sadd(key, value)
              println(startuplog) //往es中保存
            }
            MyEsUtil.indexBulk(GmallConstant.ES_INDEX_DAU, list)
            jedis.close()
          }
        }

    7、SparkStreaming接收kafka数据并处理--Hbase

    创建一个HBase表: 

    实时统计每日的分类的点击次数,存储到HBase(HBase表示如何设计的,rowkey是怎样设计)

     

     

     

    原文: https://blog.csdn.net/qq_41851454/article/details/80402483

     

    
    object DauApp {
    
      def main(args: Array[String]): Unit = {
        val sparkConf: SparkConf = new SparkConf().setAppName("dau_app").setMaster("local[*]")
        val ssc = new StreamingContext(sparkConf, Seconds(5))
        val inputDstream: InputDStream[ConsumerRecord[String, String]] = MyKafkaUtil.getKafkaStream(GmallConstant.KAFKA_TOPIC_STARTUP, ssc)
    
        //    inputDstream.foreachRDD{rdd=>
        //      println(rdd.map(_.value()).collect().mkString("\n"))
        //    }
    
        //    val dStream: DStream[String] = inputDstream.map { record =>
        //      val jsonStr: String = record.value()
        //      jsonStr
        //    }
    
        //处理数据,完了,保存偏移量
        inputDstream.foreachRDD(rdd => {
          //手动指定分区的地方
          val ranges: Array[OffsetRange] = rdd.asInstanceOf[HasOffsetRanges].offsetRanges
          println("长度=" + ranges.length)
          ranges.foreach(println)
    
          val result: RDD[(String, Int)] = rdd.map(_.value()).flatMap(_.split(",")).map((_, 1)).reduceByKey(_ + _)
          result.foreach(println)
    
          result.foreachPartition(p => {
            val jedis: Jedis = RedisUtil.getJedisClient
            p.foreach(rdd2 => {
              //      数据数理逻辑
              jedis.hincrBy("wc1", rdd2._1, rdd2._2)
            })
            //把通过hset,把对应的partition和offset写入到redis中
            val map = new util.HashMap[String, String]()
            for (o <- ranges) {
              val offset = o.untilOffset
              val partition = o.partition
              val topic = o.topic
              val group_id = "gmall_consumer_group"
              map.put("offset", offset.toString)
              jedis.hmset("offsetKey", map)
            }
            jedis.close()
          })
          // 把偏移量的Array  写入到mysql中
          //      ranges.foreach(rdd2 => {
          //        // 思考,需要保存哪些数据呢?   起始的offset不需要  还需要加上 groupid
          //        val pstm = conn.prepareStatement("replace into mysqloffset values (?,?,?,?)")
          //        pstm.setString(1, rdd2.topic)
          //        pstm.setInt(2, rdd2.partition)
          //        pstm.setLong(3, rdd2.untilOffset)
          //        pstm.setString(4, groupId)
          //        pstm.execute()
          //        pstm.close()
          //      })
    
        })
    
    
        // 转换处理
        val startuplogStream: DStream[Startuplog] = inputDstream.map {
          record =>
            val jsonStr: String = record.value()
            val startuplog: Startuplog = JSON.parseObject(jsonStr, classOf[Startuplog])
            val date = new Date(startuplog.ts)
            val dateStr: String = new SimpleDateFormat("yyyy-MM-dd HH:mm").format(date)
            val dateArr: Array[String] = dateStr.split(" ")
            startuplog.logDate = dateArr(0)
            startuplog.logHour = dateArr(1).split(":")(0)
            startuplog.logHourMinute = dateArr(1)
    
            startuplog
        }
        // 利用redis进行去重过滤
        val filteredDstream: DStream[Startuplog] = startuplogStream.transform {
          rdd =>
            println("过滤前:" + rdd.count())
            //driver  //周期性执行DataFrame
            val curdate: String = new SimpleDateFormat("yyyy-MM-dd").format(new Date)
            val jedis: Jedis = RedisUtil.getJedisClient
            val key = "dau:" + curdate
            val dauSet: util.Set[String] = jedis.smembers(key) //SMEMBERS key 获取集合里面的所有key
          val dauBC: Broadcast[util.Set[String]] = ssc.sparkContext.broadcast(dauSet)
            val filteredRDD: RDD[Startuplog] = rdd.filter {
              startuplog =>
                //executor
                val dauSet: util.Set[String] = dauBC.value
                !dauSet.contains(startuplog.mid)
            }
            println("过滤后:" + filteredRDD.count())
            filteredRDD
    
        }
    
        //去重思路;把相同的mid的数据分成一组 ,每组取第一个
        val groupbyMidDstream: DStream[(String, Iterable[Startuplog])] = filteredDstream
          .map(startuplog => (startuplog.mid, startuplog))
          .groupByKey()
    
        val distinctDstream: DStream[Startuplog] = groupbyMidDstream.flatMap {
          case (mid, startulogItr) =>
            startulogItr.take(1)
        }
    
    
        // 保存到redis中
        distinctDstream.foreachRDD { rdd =>
          // redis  type set
          // key  dau:2019-06-03    value : mids
          rdd.foreachPartition { startuplogItr =>
            //executor
            val jedis: Jedis = RedisUtil.getJedisClient
            val list: List[Startuplog] = startuplogItr.toList
            for (startuplog <- list) {
              val key = "dau:" + startuplog.logDate
              val value = startuplog.mid
              jedis.sadd(key, value)
              println(startuplog) //往es中保存
            }
            MyEsUtil.indexBulk(GmallConstant.ES_INDEX_DAU, list)
            jedis.close()
          }
        }
        ssc.start()
        ssc.awaitTermination()
      }
    }
    


     

    展开全文
  • 功能特点: 1.软件使用简单、方便,功能完备实用,上手快。 2.功能强大的利润统计功能,可以查看年,月,日的详细利润和指定某件商品销售利润。 3.极强的综合查询功能,可以按年,月,日查看详细...
  • 一个用C#开发的鞋类商品销售系统,WinForm程序。 提供了销售管理、库存管理、简单的数据统计以及系统管理等功能。 系统用户:老板, 密码:123456 技术交流请联系开发团队 开发团队联系方式系统内提供! 由于上传...
  • 《三易通服装销售系统——“前台销售”模块,“日销售统计”模块》项目总结   作者:陈显其 本次任务完成时间:2018年7月10日~2018年8月15日 开发工具与关键技术:vs2015, mvc 完成模块功能:商品选择,结算...
  • 战斗力商品销售管理系统--主要功能模块包括:客户管理、收款管理、联系回访、提醒管理、短信邮件、统计分析、商品销售、销售退货、采购进货、采购退货、库存管理、库存盘点、服务管理(一大关联模块)、办公管理(一...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,924
精华内容 769
关键字:

商品销售统计系统