ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2828|回复: 19

[求助] 讨论一个有趣的统计问题

[复制链接]

TA的精华主题

TA的得分主题

发表于 2018-8-8 17:10 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
为了说清楚,我分步说:
1.有一百个人参加一个宴会,这一百个人都有唯一的编码,分别是从100001到直到100100;
2.宴会现场有三张桌子,这三张桌子都有一个特殊的仪器,可以记录坐到这桌子的人的唯一编码;
3.这一百个人身份并不相同,有一类宾客,二类宾客,三类宾客三种,但每个人只有一种身份,不存在跨身份类别的情况;
4.每个人可以随时随地的换一张桌子吃饭,每个人只要坐到桌子边上,编码就会被桌子上的仪器记录下来,而且如果一个人来到这桌子两次,那么就记录两次编码,但在统计的时候,一个人无论来了多少次,都只能算一个人

现在问题来了,如何统计以下这几项:
1.一号、二号、三号桌分别来了多少一类宾客,二类宾客,三类宾客?
2.只参加一号桌和二号桌、只参加一号桌三号桌,只参加二号桌三号桌以及一二三号桌都参加的三类宾客分别又是多少人?

更详细的情况请参见附件

求教如何用VBA解决这个问题?

桌号分配统计.rar

8.44 KB, 下载次数: 17

TA的精华主题

TA的得分主题

发表于 2018-8-8 17:33 | 显示全部楼层
vba字典 去掉重复的编码,sql  分类统计。

TA的精华主题

TA的得分主题

发表于 2018-8-9 09:06 | 显示全部楼层
本帖最后由 sheeboard 于 2018-8-10 08:49 编辑

python写的,先去重复drop_duplicates,然后合并merge,再分组统计.
  1. one=df2['一号桌']   
  2. two=df2['二号桌']
  3. three=df2['三号桌']

  4. one=one.dropna().drop_duplicates()
  5. two=two.dropna().drop_duplicates()
  6. three=three.dropna().drop_duplicates()

  7. df1.coulumns=['id','type']
  8. one=one.to_frame(name='id')
  9. two=two.to_frame(name='id')
  10. three=three.to_frame(name='id')

  11. one_table=pd.merge(one,df1,on='id')
  12. two_table=pd.merge(two,df1,on='id')
  13. three_table=pd.merge(three,df1,on='id')

  14. one_table.groupby('type').count()
  15. two_table.groupby('type').count()
  16. three_table.groupby('type').count()
  17. 结果分别为
  18. type   
  19. 一类宾客   6
  20. 三类宾客   9
  21. 二类宾客   4

  22.       id
  23. type   
  24. 一类宾客   7
  25. 三类宾客  17
  26. 二类宾客   5

  27. type   
  28. 一类宾客   8
  29. 三类宾客  23
  30. 二类宾客  10

  31. pd.merge(one_table,two_table,on='id').groupby('type').count()
  32. ......


复制代码


TA的精华主题

TA的得分主题

发表于 2018-8-9 10:19 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 魂断蓝桥 于 2018-8-9 10:21 编辑

sql 用 UNION 去重连接,再分组就可以了。

返回结果

一类宾客
一号桌
6
三类宾客
一号桌
9
二类宾客
一号桌
4
一类宾客
三号桌
8
三类宾客
三号桌
23
二类宾客
三号桌
10
一类宾客
二号桌
7
三类宾客
二号桌
17
二类宾客
二号桌
5


代码

Sub 查询()
Dim cnn As Object
Dim Sql As String
Set cnn = CreateObject("ADODB.CONNECTION")
cnn.Open "Provider=Microsoft.ACE.OleDb.12.0;Extended Properties='Excel 12.0;HDR=YES'; Data Source=" & ThisWorkbook.FullName
Sql = "select A.类型,一号桌 AS 编号," & """一号桌"" AS 桌号" & " from [Sheet1$a1:b101] A,[Sheet1$g1:g28]  B  where A.总编号=B.一号桌" _
            & " UNION  " _
            & "select A.类型,二号桌," & """二号桌""" & " from [Sheet1$a1:b101] A,[Sheet1$i1:i48]  B  where A.总编号=B.二号桌" _
            & " UNION  " _
            & "select A.类型,三号桌," & """三号桌""" & " from [Sheet1$a1:b101] A,[Sheet1$K1:K56]  B  where A.总编号=B.三号桌"
Sheet2.Activate
Cells.ClearContents
Sql = "SELECT 类型,桌号,COUNT(*) FROM (" & Sql & ") GROUP BY 类型,桌号 order by 2,1"
[A2].CopyFromRecordset cnn.Execute(Sql)
cnn.Close: Set cnn = Nothing
End Sub


你说的 参加一号桌和二号桌
可以用
Sql = "SELECT * FROM (" & Sql & ") WHERE 桌号='一号桌'OR 桌号='二号桌'"
[e2].CopyFromRecordset cnn.Execute(Sql)



评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2018-8-9 11:01 | 显示全部楼层
'估计差不多

Option Explicit

Sub test()
  Dim arr, i, j, k, t, key, n, mark
  ReDim dic(1 To 4)
  For i = 1 To UBound(dic)
    Set dic(i) = CreateObject("scripting.dictionary")
  Next
  arr = ActiveSheet.UsedRange
  For i = 2 To UBound(arr, 1)
    If Len(arr(i, 1)) = 0 Then Exit For
    dic(4)(arr(i, 1)) = arr(i, 2)
  Next
  For i = 1 To 3
    For j = 2 To UBound(arr, 1)
      If Len(arr(j, 2 * i + 5)) = 0 Then Exit For
      If Not dic(i).exists(arr(j, 2 * i + 5)) Then
        dic(i)(arr(j, 2 * i + 5)) = dic(4)(arr(j, 2 * i + 5))
      End If
  Next j, i
  For i = 1 To 3
    ReDim cnt(1 To 3)
    For Each key In dic(i).keys
      If dic(i)(key) = "一类宾客" Then
        cnt(1) = cnt(1) + 1
      ElseIf dic(i)(key) = "二类宾客" Then
        cnt(2) = cnt(2) + 1
      Else
        cnt(3) = cnt(3) + 1
      End If
    Next
    Debug.Print i & "号桌3类客人分别为:" & Join(cnt, ",")
  Next
  Debug.Print String(50, "-")
  ReDim arr(1 To dic(4).Count + 1, 1 To 2) As String
  For Each key In dic(4).keys
    mark = vbNullString: n = n + 1
    For i = 1 To 3
      mark = mark & IIf(dic(i).exists(key), "1", "0")
    Next
    arr(n, 1) = mark: arr(n, 2) = dic(4)(key)
  Next
  For i = 1 To UBound(arr, 1) - 2
    For j = i + 1 To UBound(arr, 1) - 1
      If arr(i, 1) > arr(j, 1) Then
        t = arr(i, 1): arr(i, 1) = arr(j, 1): arr(j, 1) = t
        t = arr(i, 2): arr(i, 2) = arr(j, 2): arr(j, 2) = t
      End If
  Next j, i
  mark = Split("110 一二号 101 一三号 011 二三号 111 一二三号")
  For i = 0 To UBound(mark) Step 2
    ReDim cnt(1 To 3)
    For j = 1 To UBound(arr, 1)
      If arr(j, 1) = mark(i) Then
        For k = j To UBound(arr, 1)
          If arr(k, 1) <> mark(i) Then
            Debug.Print mark(i + 1) & "桌3类客人分别为:" & Join(cnt, ",")
            j = UBound(arr, 1): Exit For
          End If
          If arr(k, 2) = "一类宾客" Then
            cnt(1) = cnt(1) + 1
          ElseIf arr(k, 2) = "二类宾客" Then
            cnt(2) = cnt(2) + 1
          Else
            cnt(3) = cnt(3) + 1
          End If
        Next
      End If
  Next j, i
End Sub

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2018-8-9 11:32 | 显示全部楼层
代码审核中,估计差不多

1号桌3类客人分别为:6,4,9
2号桌3类客人分别为:7,5,17
3号桌3类客人分别为:8,10,23
---------------------------
一二号桌3类客人分别为:1,,1
一三号桌3类客人分别为:2,1,2
二三号桌3类客人分别为:2,2,4
一二三号桌3类客人分别为:1,1,

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-9 14:07 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
一把小刀闯天下 发表于 2018-8-9 11:01
'估计差不多

Option Explicit

太厉害了!

TA的精华主题

TA的得分主题

发表于 2018-8-9 14:42 | 显示全部楼层
问一个问题:
桌号组合,如是3个桌子就有 7种组合(2^n-1)

那么排除重复的类型统计,该向下覆盖统计吗?

比如,编号001 去了 1号桌、3号桌,类型1
那么,按桌子组合统计时,
是1号桌、3号桌、1&3号桌 各算一次类型1统计进去,实际被统计为3次(向下覆盖)
还是,仅仅按照1&3号桌统计1次?(向下不覆盖)

这里面的做法,很不一样,结果也差异很大的。

请楼主确认一下。

TA的精华主题

TA的得分主题

发表于 2018-8-9 14:59 | 显示全部楼层
'应该有7+1种组合,因为有都不参加的。所有组合全部输出

Option Explicit

Sub test()
  Dim arr, i, j, k, kk, t, key, n, mark
  ReDim dic(1 To 5)
  For i = 1 To UBound(dic)
    Set dic(i) = CreateObject("scripting.dictionary")
  Next
  mark = Split("一 二 三")
  For i = 0 To UBound(mark): dic(5)(mark(i) & "类宾客") = i + 1: Next
  arr = ActiveSheet.UsedRange
  For i = 2 To UBound(arr, 1)
    If Len(arr(i, 1)) = 0 Then Exit For
    dic(4)(arr(i, 1)) = arr(i, 2)
  Next
  For i = 1 To 3
    For j = 2 To UBound(arr, 1)
      If Len(arr(j, 2 * i + 5)) = 0 Then Exit For
      If Not dic(i).exists(arr(j, 2 * i + 5)) Then
        dic(i)(arr(j, 2 * i + 5)) = dic(4)(arr(j, 2 * i + 5))
      End If
  Next j, i
  For i = 1 To 3
    ReDim cnt(1 To 3)
    For Each key In dic(i).keys
      cnt(dic(5)(dic(i)(key))) = cnt(dic(5)(dic(i)(key))) + 1
    Next
    Debug.Print i & "号桌3类客人分别为:" & Join(cnt, ",")
  Next
  Debug.Print String(30, "-")
  ReDim arr(1 To dic(4).Count + 1, 1 To 2) As String
  For Each key In dic(4).keys
    mark = vbNullString: n = n + 1
    For i = 1 To 3
      mark = mark & IIf(dic(i).exists(key), "1", "0")
    Next
    arr(n, 1) = mark: arr(n, 2) = dic(4)(key)
  Next
  For i = 1 To UBound(arr, 1) - 2
    For j = i + 1 To UBound(arr, 1) - 1
      If arr(i, 1) > arr(j, 1) Then
        t = arr(i, 1): arr(i, 1) = arr(j, 1): arr(j, 1) = t
        t = arr(i, 2): arr(i, 2) = arr(j, 2): arr(j, 2) = t
      End If
  Next j, i
  mark = Split("000 不参加 100 一号 010 二号 001 三号 110 一二号 101 一三号 011 二三号 111 一二三号")
  For i = 0 To UBound(mark) Step 2
    ReDim cnt(1 To 3)
    For j = 1 To UBound(arr, 1)
      If arr(j, 1) = mark(i) Then
        For k = j To UBound(arr, 1)
          If arr(k, 1) <> mark(i) Then
            For kk = 1 To 3
              If Len(cnt(kk)) = 0 Then cnt(kk) = 0
            Next
            Debug.Print mark(i + 1) & "桌3类客人分别为:" & Join(cnt, ",")
            j = UBound(arr, 1): Exit For
          End If
          cnt(dic(5)(arr(k, 2))) = cnt(dic(5)(arr(k, 2))) + 1
        Next
      End If
  Next j, i
End Sub

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2018-8-9 15:00 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
'应该有7+1种组合,因为有都不参加的。代码审核中,,,

1号桌3类客人分别为:6,4,9
2号桌3类客人分别为:7,5,17
3号桌3类客人分别为:8,10,23
------------------------------
不参加桌3类客人分别为:6,8,16
一号桌3类客人分别为:2,2,6
二号桌3类客人分别为:3,2,12
三号桌3类客人分别为:3,6,17
一二号桌3类客人分别为:1,0,1
一三号桌3类客人分别为:2,1,2
二三号桌3类客人分别为:2,2,4
一二三号桌3类客人分别为:1,1,0

评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2025-1-11 20:39 , Processed in 0.029865 second(s), 20 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表