Office中國(guó)論壇/Access中國(guó)論壇

 找回密碼
 注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

12下一頁(yè)
返回列表 發(fā)新帖
查看: 7903|回復(fù): 13
打印 上一主題 下一主題

[模塊/函數(shù)] “排隊(duì)不長(zhǎng),只是很粗”——淺談化寬為長(zhǎng)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
1#
發(fā)表于 2017-3-11 18:51:57 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式

記得初中時(shí)住校吃飯?zhí)茫菚r(shí)候每周伙食費(fèi)是20元。早上1元,午餐晚餐各1.5元(周末則回家)。

早餐一般是一碗很稀的粥,上面漂浮著一塊或者兩塊油汪汪的肥肉,外加一個(gè)包子。星期三則是豬骨頭湯米粉,——當(dāng)然是沒(méi)有包子了,——所以,早操一結(jié)束,大家就集體逃亡一般奔向飯?zhí)。最開(kāi)始沖過(guò)去的在每個(gè)窗口前排成兩列,排到十幾個(gè)之后,后面的大都是女生。其它男同學(xué)則會(huì)繞到側(cè)面,伺機(jī)斜插進(jìn)去。

曾經(jīng)有個(gè)走讀的同學(xué)問(wèn)我,住校時(shí)排隊(duì)很長(zhǎng)嗎?我認(rèn)真地想了想,“排隊(duì)不長(zhǎng),只是很粗”。她笑了,“你很幽默!比缓笪乙残α,雖然我并不是一個(gè)幽默的人。直到后來(lái)學(xué)生會(huì)組織了一些學(xué)生干部專(zhuān)門(mén)去維持秩序,才開(kāi)始“化寬為長(zhǎng)”。


正如太寬的隊(duì)伍常常有不遵守秩序的嫌疑,太寬的數(shù)據(jù)表也常常有不遵守第二范式的嫌疑。而違反它,在數(shù)據(jù)庫(kù)中往往會(huì)引發(fā)很多問(wèn)題,表維護(hù)不方便,難以統(tǒng)計(jì)分析,查詢(xún)不好處理等等……所以“化寬為長(zhǎng)”就變得很重要了。

化寬為長(zhǎng)的前提是要求“寬”的那部分擁有共同的屬性,就像寬的那部分隊(duì)伍一樣(都是男同學(xué),都在隊(duì)伍側(cè)面),例如,都是數(shù)值型,都在最右邊的字段等等。如果沒(méi)有這些,當(dāng)然談不上化寬為長(zhǎng)了。先看看效果吧:

代碼如下,具體見(jiàn)示例文件。喜歡的話,就回個(gè)帖吧。

  1. Function getSQL(ByVal strTableName As String, ByVal strEndFieldName As String) As String
  2.     Dim rst As New ADODB.Recordset
  3.     Dim i As Long
  4.     Dim lngPosition As Long
  5.     Dim strSQL As String, strSQL2 As String
  6.     Dim dic As New Dictionary
  7.     Dim lngEnd As Long
  8.    
  9.     rst.Open strTableName, CurrentProject.Connection, adOpenKeyset, adLockOptimistic
  10. '查找字段分割點(diǎn)的位置
  11.     For i = 0 To rst.Fields.Count - 1
  12.         If rst.Fields(i).Name = strEndFieldName Then
  13.             lngEnd = i
  14.             Exit For
  15.         End If
  16.     Next
  17. '切割字段
  18.     For i = 0 To rst.Fields.Count - 1
  19. '在分割點(diǎn)之前,直接連接字符串
  20.         If i <= lngEnd Then
  21.             strSQL = strSQL & rst.Fields(i).Name & ","
  22.         Else
  23. '在分割點(diǎn)之后,寫(xiě)入字典,用于確定變量名和變量值。
  24.             dic.Add i, rst.Fields(i).Name
  25.             
  26.         End If
  27.     Next
  28. '關(guān)閉記錄集
  29.     rst.Close
  30.    
  31.     '準(zhǔn)備語(yǔ)句
  32.     For i = 0 To dic.Count - 1
  33.         strSQL2 = strSQL2 & "select " & strSQL & """" & _
  34.                 dic.Items(i) & """ as 變量名稱(chēng),[" & _
  35.                 dic.Items(i) & "] as 變量值 from " & strTableName & " union all "
  36.     Next
  37.    
  38.     getSQL = Left(strSQL2, Len(strSQL2) - 11)
  39.                
  40. End Function
復(fù)制代碼


本帖子中包含更多資源

您需要 登錄 才可以下載或查看,沒(méi)有帳號(hào)?注冊(cè)

x

評(píng)分

參與人數(shù) 1經(jīng)驗(yàn) +6 收起 理由
zpy2 + 6 (V幣)優(yōu)秀原創(chuàng)教程、管理建議(1-5分)

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏3 分享分享 分享淘帖 訂閱訂閱

點(diǎn)擊這里給我發(fā)消息

2#
發(fā)表于 2017-3-11 18:58:16 | 只看該作者
你總是離不開(kāi)吃

點(diǎn)擊這里給我發(fā)消息

3#
發(fā)表于 2017-3-12 07:34:12 | 只看該作者
這是傳說(shuō)中的二維轉(zhuǎn)一維嗎,贊一個(gè)

點(diǎn)擊這里給我發(fā)消息

4#
發(fā)表于 2017-3-12 10:02:54 | 只看該作者
本帖最后由 zpy2 于 2017-3-12 10:05 編輯
  1. Option Compare Database
  2. Option Explicit

  3. Function getSQL2(ByVal strTableName As String, ByVal strEndFieldName As String) As String
  4.   On Error Resume Next
  5.   Dim rst As DAO.Recordset, rst2
  6.   Dim i As Long
  7.   Dim j As Long
  8.   Dim strSQL As String, strSQL2 As String
  9.   Dim lngEnd As Long
  10.   
  11.   Set rst = CurrentDb.OpenRecordset("select * from " & strTableName)
  12.   '查找字段分割點(diǎn)的位置
  13.   For i = 0 To rst.Fields.Count - 1
  14.     If rst.Fields(i).Name = strEndFieldName Then
  15.       lngEnd = i
  16.       Exit For
  17.     End If
  18.   Next
  19.   
  20.   '這里省去了 判斷 表否存在
  21.   strSQL = "DROP TABLE tempTable"
  22.   CurrentDb.Execute strSQL
  23.   strSQL = "CREATE TABLE tempTable ("
  24.   For i = 0 To rst.Fields.Count - 1
  25.     '在分割點(diǎn)之前,直接連接字符串
  26.     If i <= lngEnd Then
  27.       strSQL = strSQL & rst.Fields(i).Name & " TEXT,"
  28.     Else
  29.       Exit For
  30.     End If
  31.   Next
  32.   strSQL = strSQL & "變量值 DOUBLE)"
  33.   CurrentDb.Execute strSQL
  34.   Rem 這段比union方法看這不同
  35.   strSQL = "SELECT * FROM tempTable"
  36.   Set rst2 = CurrentDb.OpenRecordset(strSQL)
  37.   Do While Not rst.EOF
  38.    
  39.     For i = lngEnd + 1 To rst.Fields.Count - 1
  40.       '在分割點(diǎn)之前,直接連接字符串
  41.       rst2.AddNew
  42.       For j = 0 To lngEnd
  43.         rst2.Fields(j) = rst.Fields(j)
  44.       Next
  45.       rst2.Fields(lngEnd + 1) = rst.Fields(i)
  46.       rst2.Update
  47.       
  48.     Next i
  49.     rst.MoveNext
  50.   Loop
  51.   rst2.Close
  52.   rst.Close
  53. End Function

  54. Sub runOnce()
  55.   Dim x
  56.   x = getSQL2("提成等級(jí)表", "百分點(diǎn)")
  57. End Sub



復(fù)制代碼
用臨時(shí)表作了下,好像代碼多了點(diǎn)。

本帖子中包含更多資源

您需要 登錄 才可以下載或查看,沒(méi)有帳號(hào)?注冊(cè)

x
5#
發(fā)表于 2017-3-12 10:47:14 | 只看該作者
肉一,你這是降維打擊么?
6#
 樓主| 發(fā)表于 2017-3-12 22:41:57 | 只看該作者
zpy2 發(fā)表于 2017-3-12 10:02
用臨時(shí)表作了下,好像代碼多了點(diǎn)。

創(chuàng)建臨時(shí)表有2個(gè)問(wèn)題,
1、處理字段類(lèi)型。
這里是double,換了別的,可能會(huì)是single或者long等等?紤]到通用性,所以我沒(méi)有使用這個(gè)方式。
2、插入數(shù)據(jù)的效率問(wèn)題。
創(chuàng)建臨時(shí)表一般需要嵌套循環(huán)插入,當(dāng)數(shù)據(jù)量較大時(shí)可能會(huì)有些許延時(shí)。至于修改已存在的查詢(xún)語(yǔ)句,會(huì)否存在這個(gè)問(wèn)題,暫時(shí)未測(cè)試。不過(guò),竊以為執(zhí)行選擇查詢(xún)會(huì)比追加查詢(xún)快一些。
7#
 樓主| 發(fā)表于 2017-3-12 22:43:53 | 只看該作者
紅塵如煙 發(fā)表于 2017-3-12 10:47
肉一,你這是降維打擊么?

當(dāng)時(shí)看到那個(gè)附件,想死的心都有了:
http://mzhfr.cn/thread-122659-1-1.html
8#
發(fā)表于 2017-3-13 12:15:39 | 只看該作者
我以為是腿粗呢,roych 老師為什么早餐粥上漂肥肉呀?啥飯?
9#
發(fā)表于 2017-3-13 15:01:10 | 只看該作者
生活真美好,一天20元,早餐還有肉吃。
我上學(xué)時(shí)一個(gè)月才15元的生活費(fèi)、
10#
發(fā)表于 2017-3-13 15:03:09 | 只看該作者
excel里有個(gè)逆透視
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則

QQ|站長(zhǎng)郵箱|小黑屋|手機(jī)版|Office中國(guó)/Access中國(guó) ( 粵ICP備10043721號(hào)-1 )  

GMT+8, 2025-7-16 18:14 , Processed in 0.205223 second(s), 42 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回復(fù) 返回頂部 返回列表