Office中国论坛/Access中国论坛
标题: “排队不长,只是很粗”——浅谈化宽为长 [打印本页]
作者: roych 时间: 2017-3-11 18:51
标题: “排队不长,只是很粗”——浅谈化宽为长
记得初中时住校吃饭堂,那时候每周伙食费是20元。早上1元,午餐晚餐各1.5元(周末则回家)。
早餐一般是一碗很稀的粥,上面漂浮着一块或者两块油汪汪的肥肉,外加一个包子。星期三则是猪骨头汤米粉,——当然是没有包子了,——所以,早操一结束,大家就集体逃亡一般奔向饭堂。最开始冲过去的在每个窗口前排成两列,排到十几个之后,后面的大都是女生。其它男同学则会绕到侧面,伺机斜插进去。
曾经有个走读的同学问我,住校时排队很长吗?我认真地想了想,“排队不长,只是很粗”。她笑了,“你很幽默。”然后我也笑了,虽然我并不是一个幽默的人。直到后来学生会组织了一些学生干部专门去维持秩序,才开始“化宽为长”。
正如太宽的队伍常常有不遵守秩序的嫌疑,太宽的数据表也常常有不遵守第二范式的嫌疑。而违反它,在数据库中往往会引发很多问题,表维护不方便,难以统计分析,查询不好处理等等……所以“化宽为长”就变得很重要了。
化宽为长的前提是要求“宽”的那部分拥有共同的属性,就像宽的那部分队伍一样(都是男同学,都在队伍侧面),例如,都是数值型,都在最右边的字段等等。如果没有这些,当然谈不上化宽为长了。先看看效果吧:
[attach]60945[/attach]
代码如下,具体见示例文件。喜欢的话,就回个帖吧。
- Function getSQL(ByVal strTableName As String, ByVal strEndFieldName As String) As String
- Dim rst As New ADODB.Recordset
- Dim i As Long
- Dim lngPosition As Long
- Dim strSQL As String, strSQL2 As String
- Dim dic As New Dictionary
- Dim lngEnd As Long
-
- rst.Open strTableName, CurrentProject.Connection, adOpenKeyset, adLockOptimistic
- '查找字段分割点的位置
- For i = 0 To rst.Fields.Count - 1
- If rst.Fields(i).Name = strEndFieldName Then
- lngEnd = i
- Exit For
- End If
- Next
- '切割字段
- For i = 0 To rst.Fields.Count - 1
- '在分割点之前,直接连接字符串
- If i <= lngEnd Then
- strSQL = strSQL & rst.Fields(i).Name & ","
- Else
- '在分割点之后,写入字典,用于确定变量名和变量值。
- dic.Add i, rst.Fields(i).Name
-
- End If
- Next
- '关闭记录集
- rst.Close
-
- '准备语句
- For i = 0 To dic.Count - 1
- strSQL2 = strSQL2 & "select " & strSQL & """" & _
- dic.Items(i) & """ as 变量名称,[" & _
- dic.Items(i) & "] as 变量值 from " & strTableName & " union all "
- Next
-
- getSQL = Left(strSQL2, Len(strSQL2) - 11)
-
- End Function
复制代码[attach]60947[/attach]
作者: tmtony 时间: 2017-3-11 18:58
你总是离不开吃
作者: zpy2 时间: 2017-3-12 07:34
这是传说中的二维转一维吗,赞一个
作者: zpy2 时间: 2017-3-12 10:02
本帖最后由 zpy2 于 2017-3-12 10:05 编辑
- Option Compare Database
- Option Explicit
- Function getSQL2(ByVal strTableName As String, ByVal strEndFieldName As String) As String
- On Error Resume Next
- Dim rst As DAO.Recordset, rst2
- Dim i As Long
- Dim j As Long
- Dim strSQL As String, strSQL2 As String
- Dim lngEnd As Long
-
- Set rst = CurrentDb.OpenRecordset("select * from " & strTableName)
- '查找字段分割点的位置
- For i = 0 To rst.Fields.Count - 1
- If rst.Fields(i).Name = strEndFieldName Then
- lngEnd = i
- Exit For
- End If
- Next
-
- '这里省去了 判断 表否存在
- strSQL = "DROP TABLE tempTable"
- CurrentDb.Execute strSQL
- strSQL = "CREATE TABLE tempTable ("
- For i = 0 To rst.Fields.Count - 1
- '在分割点之前,直接连接字符串
- If i <= lngEnd Then
- strSQL = strSQL & rst.Fields(i).Name & " TEXT,"
- Else
- Exit For
- End If
- Next
- strSQL = strSQL & "变量值 DOUBLE)"
- CurrentDb.Execute strSQL
- Rem 这段比union方法看这不同
- strSQL = "SELECT * FROM tempTable"
- Set rst2 = CurrentDb.OpenRecordset(strSQL)
- Do While Not rst.EOF
-
- For i = lngEnd + 1 To rst.Fields.Count - 1
- '在分割点之前,直接连接字符串
- rst2.AddNew
- For j = 0 To lngEnd
- rst2.Fields(j) = rst.Fields(j)
- Next
- rst2.Fields(lngEnd + 1) = rst.Fields(i)
- rst2.Update
-
- Next i
- rst.MoveNext
- Loop
- rst2.Close
- rst.Close
- End Function
- Sub runOnce()
- Dim x
- x = getSQL2("提成等级表", "百分点")
- End Sub
复制代码 用临时表作了下,好像代码多了点。
作者: 红尘如烟 时间: 2017-3-12 10:47
肉一,你这是降维打击么?
作者: roych 时间: 2017-3-12 22:41
创建临时表有2个问题,
1、处理字段类型。
这里是double,换了别的,可能会是single或者long等等。考虑到通用性,所以我没有使用这个方式。
2、插入数据的效率问题。
创建临时表一般需要嵌套循环插入,当数据量较大时可能会有些许延时。至于修改已存在的查询语句,会否存在这个问题,暂时未测试。不过,窃以为执行选择查询会比追加查询快一些。
作者: roych 时间: 2017-3-12 22:43
当时看到那个附件,想死的心都有了:
http://www.office-cn.net/thread-122659-1-1.html
作者: yanwei82123300 时间: 2017-3-13 12:15
我以为是腿粗呢
,roych 老师为什么早餐粥上漂肥肉呀?啥饭?
作者: Henry D. Sy 时间: 2017-3-13 15:01
生活真美好,一天20元,早餐还有肉吃。
我上学时一个月才15元的生活费、
作者: Henry D. Sy 时间: 2017-3-13 15:03
excel里有个逆透视
作者: roych 时间: 2017-3-14 17:17
超级难吃好不好,看着就觉得油腻得很了,而且有可能是猪脖子肉
作者: roych 时间: 2017-3-14 17:30
一个星期20元……一个月15,你是什么时候上学的?
作者: Henry D. Sy 时间: 2017-3-15 17:22
79年
作者: 冚友 时间: 2018-11-2 11:18
学习了,谢谢大师!
欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) |
Powered by Discuz! X3.3 |