表设计
“排队不长,只是很粗”——浅谈化宽为长
2017-04-01 16:43:30

记得初中时住校吃饭堂,那时候每周伙食费是20元。早上1元,午餐晚餐各1.5元(周末则回家)。

早餐一般是一碗很稀的粥,上面漂浮着一块或者两块油汪汪的肥肉,外加一个包子。星期三则是猪骨头汤米粉,——当然是没有包子了,——所以,早操一结束,大家就集体逃亡一般奔向饭堂。最开始冲过去的在每个窗口前排成两列,排到十几个之后,后面的大都是女生。其它男同学则会绕到侧面,伺机斜插进去。

曾经有个走读的同学问我,住校时排队很长吗?我认真地想了想,“排队不长,只是很粗”。她笑了,“你很幽默。”然后我也笑了,虽然我并不是一个幽默的人。直到后来学生会组织了一些学生干部专门去维持秩序,才开始“化宽为长”。

正如太宽的队伍常常有不遵守秩序的嫌疑,太宽的数据表也常常有不遵守第二范式的嫌疑。而违反它,在数据库中往往会引发很多问题,表维护不方便,难以统计分析,查询不好处理等等……所以“化宽为长”就变得很重要了。

化宽为长的前提是要求“宽”的那部分拥有共同的属性,就像宽的那部分队伍一样(都是男同学,都在队伍侧面),例如,都是数值型,都在最右边的字段等等。如果没有这些,当然谈不上化宽为长了。先看看效果吧:

代码如下,具体见示例文件。喜欢的话,就回个帖吧。

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