多业务场景实战-数据推断
数据推断
学习目标
- 知道数据推断的使用场景
- 使用SQL完成关键指标推断逻辑
1 业务背景:缺失关键指标
- 疫情期间,一家印度外卖餐厅想通过数据分析,数据挖掘提升销量,但是在历史数据中缺少了很重要的一个维度,用餐人数
- 每单客人的就餐人数这一信息对于我们优化服务流程,设计套餐都有很大的指导意义
- 从现在开始改造出餐系统,添加就餐人数字段,但是涉及工作量较大(前后端开发,数据库调整),并且改造完成后需要几个月之后积累了一定的数据量可以进行进一步分析
- 从现有的数据中可以推理出每单的就餐人数,虽然会存在一定误差,但可以利用全部的历史数据,快速上线
2 业务数据介绍
- 有两家餐厅的业务数据
- 订单表:
Order_Number
订单编号Order_Date
订单日期Item_Name
商品名称Quantity
商品数量Product_Price
商品价格Total_products
订单商品数量restaurant_no
连锁店编号
Order_Number | Order_Date | Item_Name | Quantity | Product_Price | Total_products | restaurant_no |
---|---|---|---|---|---|---|
16118 | 03/08/2019 20:25 | Plain Papadum | 2 | 0.8 | 6 | 1 |
16118 | 03/08/2019 20:25 | King Prawn Balti | 1 | 12.95 | 6 | 1 |
16118 | 03/08/2019 20:25 | Garlic Naan | 1 | 2.95 | 6 | 1 |
16118 | 03/08/2019 20:25 | Mushroom Rice | 1 | 3.95 | 6 | 1 |
16118 | 03/08/2019 20:25 | Paneer Tikka Masala | 1 | 8.95 | 6 | 1 |
16118 | 03/08/2019 20:25 | Mango Chutney | 1 | 0.5 | 6 | 1 |
16117 | 03/08/2019 20:17 | Plain Naan | 1 | 2.6 | 7 | 1 |
16117 | 03/08/2019 20:17 | Mushroom Rice | 1 | 3.95 | 7 | 1 |
16117 | 03/08/2019 20:17 | Tandoori Chicken (1/4) | 1 | 4.95 | 7 | 1 |
16117 | 03/08/2019 20:17 | Vindaloo - Lamb | 1 | 7.95 | 7 | 1 |
16117 | 03/08/2019 20:17 | Chapati | 1 | 1.95 | 7 | 1 |
16117 | 03/08/2019 20:17 | Lamb Tikka | 1 | 4.95 | 7 | 1 |
16117 | 03/08/2019 20:17 | Saag Paneer | 1 | 5.95 | 7 | 1 |
16116 | 03/08/2019 20:09 | Aloo Chaat | 1 | 4.95 | 5 | 1 |
- 菜单表:
- 商品名称
- 商品价格
item_name | product_price | restaurant_id |
---|---|---|
Achar Chicken | 8.95 | 2 |
Achar Lamb | 8.95 | 2 |
Aloo Brinjal | 5.95 | 2 |
Aloo Chaat | 4.95 | 1 |
Aloo Chaat | 4.95 | 2 |
Aloo Dupiaza | 5.95 | 2 |
Aloo Gobi | 5.95 | 1 |
Aloo Gobi | 5.95 | 2 |
Aloo Methi | 5.95 | 1 |
Aloo Mithy | 5.95 | 2 |
Aloo Peas | 5.95 | 2 |
3 基本思路
如何根据上述数据确定就餐人数?
- 我们可以将菜单数据划分为几类,根据不同类别食物的点单量来推断就餐人数
- 主食:Naan(囊), Rice(米饭)
- 饮料:Cola(可乐)COBRA(啤酒)
- 小吃:samosa(咖喱角)Seekh Kebab (烤串)
酱料:pickle(腌菜) Chutney
主菜: LAMB TIKKA 烤羊肉 Prawn Karahi Masala 咖喱虾
确定推断规则:
- 1份主食对应1人 (1:1)
- 1份主菜对应1人 (1:1)
- 1份饮料对应1人(1:1)
- 2份小食对应1人 (0.5:1)
- 酱料,佐料不做计算(n:0)
规则验证:推断就餐人数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4ODATd8J-1631535784872)(img\indian_food1.png)]
- 主食一份:naan(1:1) , 饮料一份:酸奶(1:1), 菜酱料 4
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7IlZPLys-1631535784874)(img\indian-food2.png)]
主食:两份米饭+一份馕饼=3人份
饮料:一份酸奶=1人份
主菜: 3个 = 3人份
小食:1份脆饼+6份菜=0.5*7=3.5人份
佐料&配菜:2份酱料=n*0=0人份
按照四类中取最大值的原则,我们可得这顿饭的就餐人数为
Max(3人份,3人份,3.5人份,0人份)=3.5人,由于人数不能出现小数,向下取整 = 3人
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4p8JnJH6-1631535784875)(img\bear.png)]
- 上面一餐算几人?
- 主食:没有
- 饮料:40瓶啤酒
- 小食:……
- 酱料:n*0
- 按照上述原则 上面一餐推断出来的人数为40人——如果专门以喝酒为目的的聚餐,上述规则推断出来的出错概率很高
- 这种极端的例子可以验证在数据中的占比,如果占比不大则无太大影响
4 代码实现
使用SQL批量处理数据实现数据推断逻辑
#mermaid-svg-JDcV8s3CSTwk4R3F .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .label text{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .node rect,#mermaid-svg-JDcV8s3CSTwk4R3F .node circle,#mermaid-svg-JDcV8s3CSTwk4R3F .node ellipse,#mermaid-svg-JDcV8s3CSTwk4R3F .node polygon,#mermaid-svg-JDcV8s3CSTwk4R3F .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-JDcV8s3CSTwk4R3F .node .label{text-align:center;fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .node.clickable{cursor:pointer}#mermaid-svg-JDcV8s3CSTwk4R3F .arrowheadPath{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-JDcV8s3CSTwk4R3F .flowchart-link{stroke:#333;fill:none}#mermaid-svg-JDcV8s3CSTwk4R3F .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-JDcV8s3CSTwk4R3F .edgeLabel rect{opacity:0.9}#mermaid-svg-JDcV8s3CSTwk4R3F .edgeLabel span{color:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-JDcV8s3CSTwk4R3F .cluster text{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-JDcV8s3CSTwk4R3F .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-JDcV8s3CSTwk4R3F text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-JDcV8s3CSTwk4R3F .actor-line{stroke:grey}#mermaid-svg-JDcV8s3CSTwk4R3F .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-JDcV8s3CSTwk4R3F #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .sequenceNumber{fill:#fff}#mermaid-svg-JDcV8s3CSTwk4R3F #sequencenumber{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F #crosshead path{fill:#333;stroke:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .messageText{fill:#333;stroke:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-JDcV8s3CSTwk4R3F .labelText,#mermaid-svg-JDcV8s3CSTwk4R3F .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-JDcV8s3CSTwk4R3F .loopText,#mermaid-svg-JDcV8s3CSTwk4R3F .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-JDcV8s3CSTwk4R3F .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-JDcV8s3CSTwk4R3F .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-JDcV8s3CSTwk4R3F .noteText,#mermaid-svg-JDcV8s3CSTwk4R3F .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-JDcV8s3CSTwk4R3F .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-JDcV8s3CSTwk4R3F .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-JDcV8s3CSTwk4R3F .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-JDcV8s3CSTwk4R3F .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .section{stroke:none;opacity:0.2}#mermaid-svg-JDcV8s3CSTwk4R3F .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-JDcV8s3CSTwk4R3F .section2{fill:#fff400}#mermaid-svg-JDcV8s3CSTwk4R3F .section1,#mermaid-svg-JDcV8s3CSTwk4R3F .section3{fill:#fff;opacity:0.2}#mermaid-svg-JDcV8s3CSTwk4R3F .sectionTitle0{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .sectionTitle1{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .sectionTitle2{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .sectionTitle3{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-JDcV8s3CSTwk4R3F .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .grid path{stroke-width:0}#mermaid-svg-JDcV8s3CSTwk4R3F .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-JDcV8s3CSTwk4R3F .task{stroke-width:2}#mermaid-svg-JDcV8s3CSTwk4R3F .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .taskText:not([font-size]){font-size:11px}#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-JDcV8s3CSTwk4R3F .task.clickable{cursor:pointer}#mermaid-svg-JDcV8s3CSTwk4R3F .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-JDcV8s3CSTwk4R3F .taskText0,#mermaid-svg-JDcV8s3CSTwk4R3F .taskText1,#mermaid-svg-JDcV8s3CSTwk4R3F .taskText2,#mermaid-svg-JDcV8s3CSTwk4R3F .taskText3{fill:#fff}#mermaid-svg-JDcV8s3CSTwk4R3F .task0,#mermaid-svg-JDcV8s3CSTwk4R3F .task1,#mermaid-svg-JDcV8s3CSTwk4R3F .task2,#mermaid-svg-JDcV8s3CSTwk4R3F .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutside0,#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutside2{fill:#000}#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutside1,#mermaid-svg-JDcV8s3CSTwk4R3F .taskTextOutside3{fill:#000}#mermaid-svg-JDcV8s3CSTwk4R3F .active0,#mermaid-svg-JDcV8s3CSTwk4R3F .active1,#mermaid-svg-JDcV8s3CSTwk4R3F .active2,#mermaid-svg-JDcV8s3CSTwk4R3F .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-JDcV8s3CSTwk4R3F .activeText0,#mermaid-svg-JDcV8s3CSTwk4R3F .activeText1,#mermaid-svg-JDcV8s3CSTwk4R3F .activeText2,#mermaid-svg-JDcV8s3CSTwk4R3F .activeText3{fill:#000 !important}#mermaid-svg-JDcV8s3CSTwk4R3F .done0,#mermaid-svg-JDcV8s3CSTwk4R3F .done1,#mermaid-svg-JDcV8s3CSTwk4R3F .done2,#mermaid-svg-JDcV8s3CSTwk4R3F .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-JDcV8s3CSTwk4R3F .doneText0,#mermaid-svg-JDcV8s3CSTwk4R3F .doneText1,#mermaid-svg-JDcV8s3CSTwk4R3F .doneText2,#mermaid-svg-JDcV8s3CSTwk4R3F .doneText3{fill:#000 !important}#mermaid-svg-JDcV8s3CSTwk4R3F .crit0,#mermaid-svg-JDcV8s3CSTwk4R3F .crit1,#mermaid-svg-JDcV8s3CSTwk4R3F .crit2,#mermaid-svg-JDcV8s3CSTwk4R3F .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-JDcV8s3CSTwk4R3F .activeCrit0,#mermaid-svg-JDcV8s3CSTwk4R3F .activeCrit1,#mermaid-svg-JDcV8s3CSTwk4R3F .activeCrit2,#mermaid-svg-JDcV8s3CSTwk4R3F .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-JDcV8s3CSTwk4R3F .doneCrit0,#mermaid-svg-JDcV8s3CSTwk4R3F .doneCrit1,#mermaid-svg-JDcV8s3CSTwk4R3F .doneCrit2,#mermaid-svg-JDcV8s3CSTwk4R3F .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-JDcV8s3CSTwk4R3F .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-JDcV8s3CSTwk4R3F .milestoneText{font-style:italic}#mermaid-svg-JDcV8s3CSTwk4R3F .doneCritText0,#mermaid-svg-JDcV8s3CSTwk4R3F .doneCritText1,#mermaid-svg-JDcV8s3CSTwk4R3F .doneCritText2,#mermaid-svg-JDcV8s3CSTwk4R3F .doneCritText3{fill:#000 !important}#mermaid-svg-JDcV8s3CSTwk4R3F .activeCritText0,#mermaid-svg-JDcV8s3CSTwk4R3F .activeCritText1,#mermaid-svg-JDcV8s3CSTwk4R3F .activeCritText2,#mermaid-svg-JDcV8s3CSTwk4R3F .activeCritText3{fill:#000 !important}#mermaid-svg-JDcV8s3CSTwk4R3F .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-JDcV8s3CSTwk4R3F g.classGroup text .title{font-weight:bolder}#mermaid-svg-JDcV8s3CSTwk4R3F g.clickable{cursor:pointer}#mermaid-svg-JDcV8s3CSTwk4R3F g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-JDcV8s3CSTwk4R3F g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-JDcV8s3CSTwk4R3F .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-JDcV8s3CSTwk4R3F .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-JDcV8s3CSTwk4R3F .dashed-line{stroke-dasharray:3}#mermaid-svg-JDcV8s3CSTwk4R3F #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F .commit-id,#mermaid-svg-JDcV8s3CSTwk4R3F .commit-msg,#mermaid-svg-JDcV8s3CSTwk4R3F .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-JDcV8s3CSTwk4R3F g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-JDcV8s3CSTwk4R3F g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-JDcV8s3CSTwk4R3F g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-JDcV8s3CSTwk4R3F .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-JDcV8s3CSTwk4R3F .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-JDcV8s3CSTwk4R3F .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-JDcV8s3CSTwk4R3F .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-JDcV8s3CSTwk4R3F .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-JDcV8s3CSTwk4R3F .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-JDcV8s3CSTwk4R3F .edgeLabel text{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-JDcV8s3CSTwk4R3F .node circle.state-start{fill:black;stroke:black}#mermaid-svg-JDcV8s3CSTwk4R3F .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-JDcV8s3CSTwk4R3F #statediagram-barbEnd{fill:#9370db}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-state .divider{stroke:#9370db}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-JDcV8s3CSTwk4R3F .note-edge{stroke-dasharray:5}#mermaid-svg-JDcV8s3CSTwk4R3F .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-JDcV8s3CSTwk4R3F .error-icon{fill:#522}#mermaid-svg-JDcV8s3CSTwk4R3F .error-text{fill:#522;stroke:#522}#mermaid-svg-JDcV8s3CSTwk4R3F .edge-thickness-normal{stroke-width:2px}#mermaid-svg-JDcV8s3CSTwk4R3F .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-JDcV8s3CSTwk4R3F .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-JDcV8s3CSTwk4R3F .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-JDcV8s3CSTwk4R3F .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-JDcV8s3CSTwk4R3F .marker{fill:#333}#mermaid-svg-JDcV8s3CSTwk4R3F .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-JDcV8s3CSTwk4R3F {color: rgba(0, 0, 0, 0.75);font: ;}判断就餐人数统计每单交易的主食数量四者取最大值,小数向下取整统计每单交易的饮料数量统计每单交易的主菜数量统计每单交易的小食数量酱料不统计SQL作业流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TO83TFxY-1631535784878)(img\sql2.png)]
原始数据中缺少菜品类别标签,需要先添加菜品类别标签
使用
LOCATE
函数 进行字符串匹配,使用CASE WHEN
语句判断不同条件,创建新字段food_category
LOCATE 函数介绍:
LOCATE(substr,str)
返回 substr 在 str中的位置- substr, 要查询的子串
- str 字段名字 或者 字符串
DROP TABLE IF EXISTS food_category; CREATE TABLE food_category AS SELECT Item_Name AS item_name, `Product_Price` AS price, Restaurant_id AS restaurant_id, CASEWHEN locate( 'Dahi', Item_Name )> 0 THEN '酸奶' WHEN locate( 'wine', Item_Name )> 0 OR locate( 'COBRA', Item_Name )> 0 THEN '酒' WHEN locate( 'water', Item_Name )> 0 OR locate( 'Coke', Item_Name )> 0 OR locate( 'Lemonade', Item_Name )> 0 THEN '饮料' WHEN locate( 'Rice', Item_Name )> 0 THEN '米饭' WHEN locate( 'Chapati', Item_Name )> 0 OR locate( 'Paratha', Item_Name )> 0 OR locate( 'Naan', Item_Name )> 0 OR locate( 'roti', Item_Name )> 0 OR locate( 'Papadum', Item_Name )> 0 THEN '饼' WHEN locate ( 'Main', Item_Name )> 0 THEN '主菜' WHEN locate ( 'Chaat', Item_Name )> 0 OR locate( 'Muttar', Item_Name )> 0 THEN '小吃' WHEN locate( 'Chicken', Item_Name )> 0 THEN '鸡肉类' WHEN locate( 'Lamb', Item_Name )> 0 THEN '羊肉类' WHEN locate( 'Fish', Item_Name )> 0 THEN '鱼肉类' WHEN locate( 'Prawn', Item_Name )> 0 OR locate( 'Jinga', Item_Name )> 0 THEN '虾类' WHEN locate( 'Pakora', Item_Name )> 0 THEN '炸素丸子' WHEN LOCATE( 'Saag', Item_Name )> 0 THEN'绿叶菜胡胡' WHEN locate( 'Paneer', Item_Name )> 0 THEN'芝士菜' WHEN locate( 'Pickle', Item_Name )> 0 OR locate( 'Chutney', Item_Name )> 0 THEN'腌菜' WHEN locate( 'Aloo', Item_Name )> 0 THEN'土豆类' WHEN locate( 'Salad', Item_Name )> 0 THEN'沙拉' WHEN locate( 'Tikka', Item_Name )> 0 THEN'烤串' WHEN locate( 'Chana', Item_Name )> 0 THEN'豆类' WHEN locate( 'Dall', Item_Name )> 0 OR locate( 'Hari Mirch', Item_Name )> 0 THEN'素菜' WHEN locate( 'Puree', Item_Name )> 0 THEN'胡胡' WHEN locate( 'Raitha', Item_Name )> 0 OR locate( 'Raita', Item_Name )> 0 THEN'酸奶沙拉' WHEN locate( 'French Fries', Item_Name )> 0 THEN'炸薯条' WHEN locate( 'Samosa', Item_Name )> 0 THEN'咖喱角' WHEN locate( 'Kehab', Item_Name )> 0 OR locate( 'Kebab', Item_Name )> 0 THEN'烤串(小食)' WHEN locate( 'Bhajee', Item_Name )> 0 OR locate( 'Bhaji', Item_Name )> 0 THEN'油炸蔬菜团' WHEN locate( 'Mushroom', Item_Name )> 0 OR locate( 'Vegetable', Item_Name )> 0 THEN'蔬菜' WHEN locate( 'Starter', Item_Name )> 0 THEN'开胃小吃' WHEN locate( 'Sauce', Item_Name )> 0 THEN'酱' ELSE '咖喱菜' END AS food_category FROMrestaurant_products_price;
首先看一下产品明细表,知道我们数据库内现有的产品划分,找到与我们推理时用到的分类之间的差异。
SELECTcount( DISTINCT item_name ) AS item_num,food_category FROMfood_category GROUP BYfood_category ORDER BYitem_num DESC;
在现有的产品明细表里重新定义一列字段,作为我们就餐人数判断的产品分类
drop table if exists food_type; create table food_type as SELECTitem_name,price,restaurant_id,food_category, CASEWHEN food_category IN ( '鸡肉类', '羊肉类', '虾类', '咖喱菜', '鱼肉类', '主菜', '芝士菜' ) THEN'主菜' WHEN food_category IN ( '饼', '米饭' ) THEN'主食' WHEN food_category IN ( '饮料', '酒', '酸奶' ) THEN'饮料' WHEN food_category IN ( '酱', '腌菜' ) THEN'佐料' ELSE '小食' END AS food_type FROMfood_category;
再来看一下重新定义过后产品的分类情况
SELECTcount( DISTINCT item_name ) AS item_num,food_type,food_category FROMfood_type GROUP BYfood_type,food_category ORDER BYfood_type,food_category,item_num DESC;
将交易明细表与我们刚定义的产品明细表进行关联,把产品分类和价格加入明细当中
SELECTa.*,b.food_type,b.price FROMrestaurant_orders aJOIN food_type b ON a.`Item_Name` = b.item_name AND a.Restaurant_Id = b.restaurant_id;
目前一行记录是一笔订单的一种产品的售卖情况,如果一笔订单有若干样产品会分成若干行,我们希望把一笔订单的详情,从多行统一到一行中,同时用我们事先定义的系数计算。
select a.`Order_Number`,a.`Order_Date`,a.restaurant_id,round(sum(a.Quantity*b.price),2) as total_amount, sum(case when food_type='主食' then a.Quantity*1 else 0 end) as staple_food_count, sum(case when food_type='主菜' then a.Quantity*1 else 0 end) as main_course_count, sum(case when food_type='饮料' then a.Quantity*1 else 0 end) as drink_count, sum(case when food_type='小食' then a.Quantity*0.5 else 0 end) as snack_count from restaurant_orders a join food_type b on a.`Item_Name`=b.item_name and a.Restaurant_Id=b.restaurant_id group by a.`Order_Number`,a.`Order_Date`,a.Restaurant_Id;
比较主食,主菜,饮料,小食中的最大者
select c.*,GREATEST(c.staple_food_count,c.main_course_count,c.drink_count,c.snack_count) as max_count from (select a.`Order_Number`,a.`Order_Date`,a.restaurant_id,round(sum(a.Quantity*b.price),2) as total_amount, sum(case when food_type='主食' then a.Quantity*1 else 0 end) as staple_food_count, sum(case when food_type='主菜' then a.Quantity*1 else 0 end) as main_course_count, sum(case when food_type='饮料' then a.Quantity*1 else 0 end) as drink_count, sum(case when food_type='小食' then a.Quantity*0.5 else 0 end) as snack_count from restaurant_orders a join food_type b on a.`Item_Name`=b.item_name and a.Restaurant_Id=b.restaurant_id group by a.`Order_Number`,a.`Order_Date`,a.Restaurant_Id) c;
最后,增加向下取整的逻辑,并且确保最小就餐人数为1
select c.*, GREATEST(floor(GREATEST(c.staple_food_count,c.main_course_count,c.drink_count,c.snack_count)),1) as customer_count from (select a.`Order_Number`,a.`Order_Date`,a.restaurant_id,round(sum(a.Quantity*b.price),2) as total_amount, sum(case when food_type='主食' then a.Quantity*1 else 0 end) as staple_food_count, sum(case when food_type='主菜' then a.Quantity*1 else 0 end) as main_course_count, sum(case when food_type='饮料' then a.Quantity*1 else 0 end) as drink_count, sum(case when food_type='小食' then a.Quantity*0.5 else 0 end) as snack_count from restaurant_orders a join food_type b on a.`Item_Name`=b.item_name and a.Restaurant_Id=b.restaurant_id group by a.`Order_Number`,a.`Order_Date`,a.Restaurant_Id) c;
新建一张表格,将两家店每一笔交易的时间,金额,就餐人数,主食,饮料,小食数存储进去
DROP TABLE IF EXISTS restaurants_orders_customer_count; CREATE TABLE restaurants_orders_customer_count AS SELECT c.*, GREATEST( floor( GREATEST( c.staple_food_count, c.main_course_count, c.drink_count, c.snack_count )), 1 ) AS customer_count FROM(SELECTa.`Order_Number`,a.`Order_Date`,a.restaurant_id,round( sum( a.Quantity * b.price ), 2 ) AS total_amount,sum( CASE WHEN food_type = '主食' THEN a.Quantity * 1 ELSE 0 END ) AS staple_food_count,sum( CASE WHEN food_type = '主菜' THEN a.Quantity * 1 ELSE 0 END ) AS main_course_count,sum( CASE WHEN food_type = '饮料' THEN a.Quantity * 1 ELSE 0 END ) AS drink_count,sum( CASE WHEN food_type = '小食' THEN a.Quantity * 0.5 ELSE 0 END ) AS snack_count FROMrestaurant_orders aJOIN food_type b ON a.`Item_Name` = b.item_name AND a.Restaurant_Id = b.restaurant_id GROUP BYa.`Order_Number`,a.`Order_Date`,a.Restaurant_Id ) c;
检查一下之前担心的饮料过多导致的推测异常占比
SELECTcount( CASE WHEN drink_count >= 5 THEN `Order_Number` ELSE NULL END ) AS outlier_count,count(*) AS total_count,round( count( CASE WHEN drink_count >= 5 THEN `Order_Number` ELSE NULL END )/ count(*), 5 ) AS outlier_rate FROMrestaurants_orders_customer_count;
outlier_count total_count outlier_rate 13 33055 0.0004 有了就餐人数之后,我们还可以进行进一步分析
SELECTrestaurant_id,avg( customer_count ) AS avg_cc,avg( total_amount ) AS ta,avg( total_amount / customer_count ) AS avg_scc,avg( staple_food_count / customer_count ) AS avg_staple,avg( main_course_count / customer_count ) AS avg_main,avg( drink_count / customer_count ) AS avg_drink,avg( snack_count / customer_count ) AS avg_snake FROMrestaurants_orders_customer_count group by restaurant_id;
5 结果解读
- 有了就餐人数之后,我们能够增添许多新KPI,例如人均花费,人均产品数等
- 根据新增的就餐人数,我们可以学习每天各个时段的用餐场景。例如什么时候最有可能一人食,什么时候最有可能2人约饭,什么时候最有可能多人聚餐等。
- 对于就餐人数比较固定的用户,我们是否可以考虑推出一些定制化的套餐或者促销产品,促进每个餐期的营业表现?
6 小结
- 现实生活中,我们会遇到一些问题,问题的答案不能直接获取,但可以推理得到,例如:
- 煎饼摊的老板没仔细算过每天能做多少个煎饼,但通过用了多少面粉可以推算出来
- 突然有人问你今天是几号,你一时不记得但转念想到明天预约了植树节的亲子活动。
- 数据推断的价值:
- 数据本身就是资产,而获取新数据的成本不断增加,数据推断的价值愈发突出
- 数据推断是基于已经存在的数据资产,发掘出来的“新”数据,相当于是已较低的成本增加了数据资产
多业务场景实战-数据推断相关推荐
- 共享快递柜业务场景实战(服务构建)
简介: 使用物联网平台,快速构建一个高性能的共享快递柜业务 1.背景 当我们的设备和物联网平台建立mqtt连接通道后,会根据业务需求传输不同的数据.本次以共享快递柜业务场景讲解topic和payloa ...
- 不同业务场景下数据同步方案设计
企业开发实践中通常需要提供数据搜索的功能,例如,电商系统中的商品搜索.订单搜索等.通常,搜索任务通常由搜索引擎担当.如Elasticsearch.而我们的原始数据为了安全性等问题通常存储在关系型数据库 ...
- CO内外部记账数据对应数据库表(COSP、COSS、COEP、COBK、TBO01)和业务场景操作示例
文章目录 一.CO记账数据来源的业务场景 二.业务场景示例 2.1 业务场景一示例 2.1.1 FI财务记账计入费用 2.1.2 费用型采购订单计入费用 2.2 业务场景二示例 三.记账数据对应数据库 ...
- 不同业务场景下如何进行数据库水平切分?
很多互联网业务,有着数据量大的特点,随着数据量的逐步增加,数据库逐渐成为系统的瓶颈. 主从同步读写分离的架构方案只能提升数据库的读性能,对单库数据量的膨胀,以及写性能的瓶颈并不能够很好解决.此时数据库 ...
- 我是如何在一家独角兽公司做业务中台、数据中台的?8页ppt详解中台建设实践!...
点击"技术领导力"关注∆ 每天早上8:30推送 概述 中台这个词火爆挺久了.但从阿里 2015 年提出并开始实施,发展到目前为止,并没有「标准化」:换句话说,它跟「人工智能」,「 ...
- 多场景业务-数据推断
数据推断 学习目标 知道数据推断的使用场景 使用SQL完成关键指标推断逻辑 1 业务背景:缺失关键指标 疫情期间,一家印度外卖餐厅想通过数据分析,数据挖掘提升销量,但是在历史数据中缺少了很重要的一个维 ...
- 开放下载!《阿里巴巴大数据及AI实战》深度解析典型场景大数据实践
来源:开发者社区 本文约2000字,建议阅读5分钟. 阿里经济体大数据及AI典型场景最佳实践全揭秘.2019不容错过的大数据实战手册--<阿里巴巴大数据及AI实战>现在可以免费下载阅读啦! ...
- 阿里开发者们的第15个感悟:做一款优秀大数据引擎,要找准重点解决的业务场景
2015年12月20日,云栖社区上线.2018年12月20日,云栖社区3岁. 阿里巴巴常说"晴天修屋顶". 在我们看来,寒冬中,最值得投资的是学习,是增厚的知识储备. 所以社区特别 ...
- 百亿条数据复杂业务场景下通用归因模型设计实现
1 背景 互联网流量应用的一个重要方面是计算各页面.入口的转化,深度洞察用户行为轨迹,数据驱动精细化运营,对一些大公司来说也是如此.如何建设公司级统一口径转化导流分析数据,满足多个业务对转化数据的需求 ...
最新文章
- 一行代码都不用写,教你如何快速搭建Github博客!!!
- 白牌交换机有什么特点?与传统换机相比有什么特别之处?
- eclipse中设置Linux编码环境,更改eclipse中console编码
- 中国溶解浆市场深度调研及投资战略决策报告2022-2028年版
- leetcode203 移除链表元素
- 33个常见问题!超全Windows排查手册
- 7年专科生程序员同时去腾讯和微软面试,问HR结果以为听错了,结局反转!!
- Redmi发布98寸电视:屏占比98.8%、价格仅为友商1/5
- linux 中常见的压缩和解压缩的命令
- JDK 和 tomcat 安装 配置
- 毕业设计-JavaWeb项目《图书馆借阅管理系统》-附源码
- 网络监控软件百络网警 v6.6b 家庭版 下载
- 某选煤厂智能智能化解决方案
- archlinux 分区
- 加州大学戴维斯分校 计算机科学,美国王牌专业!加州大学戴维斯分校计算机科学专业等你来...
- AWS Lambda重大更新,跨越编程语言差异之门?
- 阿姆斯特朗数——————还记得大明湖畔的水仙花么(笑)
- AD软件PCB快捷键
- Android 获得手机ip
- 2019 初入IT十年(下)---- 视线所及只剩生活
热门文章
- NSX-T 系列:第 8部分 - 添加Edge节点和配置Edge集群
- Java 8 Stream:遍历、筛选、指定、排序、统计等
- K-anonymity 2-anonymous
- 非常NB的一款快捷启动软件--Merry
- 计算机硬盘的主流型号,四款主流2.5英寸笔记本机械硬盘性能对比
- 提取DELL的SWM工厂镜像安装到虚拟机
- 实习笔记 —— Git II(远程提交)
- 会计中级职称计算机考试报名时间2015年,2021年中级会计职称考试时间是几天?...
- 【Java基础】循环、嵌套、跳转控制break/continue、调试器、函数
- 手机数控模拟器安卓版_安卓版数控机床模拟器下载-数控机床模拟器手机版下载v1.1.4 高级版-乐游网安卓下载...