2008-05-03

請問 SQL 如何顯示重複的資料


問題:

我用 VB + ACCESS 設計購屋貸款的資料庫程式,有一個 TABLE 需用 ID 欄位 (身分證號) 過濾重複資料。假設有 C120012666 有三筆資料,E222272777一筆,使用 SQL 指令「SELECT DISTINCT ID FROM TABLE1」會顯示兩筆資料,也就是 C120012666、E222272777 各一筆。

如果我想抓出「有重複」的資料但過濾「沒有重複」資料,
就是我只要顯示 C120012666 那三筆而不顯示 E222272777 那一筆,請問 SQL 語法有哪種指令可以做到?


回答:

如果你想用一行指令是可以做到的:

select * from Table1 where ID in (select ID from Table1 group by ID having count(ID) >1 )

一行指令就做到看起來很神奇,不過請注意執行速度的問題,因為它對每一筆資料都作了子查詢,想想看如果你的 Table1 有一百萬筆資料,那是多麼可怕的事情!

從系統效益面來看,過濾重複 ID 是一個經常需要處理的狀況,如果先將「select ID, count(ID) as IDCount from Table1 group by ID」這個動作建立一個「Query1」,再用下面的指令來過濾資料就會比較有效率:

select Table1.* from Table1 inner join Query1
on Table1.ID = Query1.ID and Query1.IDCount > 1

這個指令在執行時「Query1」的查詢結果會先建立並且只執行一次,然後這個暫存結果才會與 Table1 作 Inner Join。

2008-05-02

EXCEL 檔案連結問題


問題:

我有一份日報表,其內容為 31 天的分類夾A欄為日期,B、C....為各種收入欄位但我的老闆自己也作了一每日收入明細表資料來自我的日報表,只是編排格式不同,我不想重新輸打相同的資料,請問我要如何依A欄的日期從我的日報表抓取收入資料到老闆的收入明細表?


回答:

使用 DLookUp 函數可以依據查詢條件譬如你的日期,去其他工作表或者其他 Excel 檔案找資料。

你可以將你的日報表複製到固定的資料夾位置,譬如和老闆的收入明細表放在一起,然後在老闆收入明細表每一天每一項收入欄位使用 DLookUp 來寫公式,每一欄都是以日期 (如 1/10,看你日期用什麼格式) 到你的日報表去找該欄的資料回來。

基本上公式寫過一次以後,只要每個月將你的日報表複製過來,老闆收入明細表也就出來了。

瀏覽 Access 資料記錄時的觸發條件


問題:


請問當 Access 用戶瀏覽上一筆或下一筆 Record 時觸發的事件為何?應該使用以下哪種事件?

On Current
On Open
On Load
On Active
On Timer


回答:

On Current 就是作資料記錄瀏覽時會觸發的事件,新增記錄時也會觸發。

On Open 以及 On Load 都是開啟表單時觸發,On Open 會先發生。On Active 則是表單取得駐點時觸發,開啟表單時也會在 On Load 之後觸發。

On Timer 是當你設定表單的 TimerInterval 屬性後,就會每隔這個時間 (以毫秒為單位) 發生一次。

請問如何用 SQL 語法來建立資料表?


問題:

CREATE TABLE book_bill (
 user_id char(10) not null PRIMARY KEY,
 book_id char(10) not null ,
 loan_date char(10) not null,
 due_date char(10) not null,
 fee char(10) not null
)

GO

在上面的語法中,我想將 user_id 和 book_id 設成 primary key,但我在 query analyzer 執行時無法成功,請問該怎麼修改語法才能將這兩個欄位設定成 primary key?


回答:

首先將上面 user_id 後面的 PRIMARY KEY 去掉,然後在這個敘述之後加入下面的敘述:

ALTER TABLE book_bill WITH NOCHECK ADD
CONSTRAINT [PK_book_bill] PRIMARY KEY CLUSTERED
(
 [user_id],
 [book_id]
) ON [PRIMARY]

GO

使用 Access 表單要如何重覆上一筆 key-in 的資料?


問題:


我想做一個表單,欄位有日期、機台、訂位等,想在 key 完一筆資料後,將此筆資料保留至下一筆要新 key 的資料欄位,以避免相同資料重覆 key-in,只需將不同資料欄位輸入即可。

有人建議我用:Me.機台.DefultValue = Me.機台

但是這只能用文字的欄位,日期欄位則不能使用,用了會跳出像是 1900 這樣的年號,請問有沒有其他的好方法?


回答:

你只要在表單的 AfterInsert 事件程序內將你想保留的欄位值儲存在表單層次的變數中,而在 BeforeInsert 事件程序內將變數中的值設定到你要重覆的欄位就可以了。請參考以下的程式碼:

'
表單變數宣告 (配合表單資料欄位型態)
Private OrderDate as Date ' 日期
Private MachID as Integer ' 機台
Private OrderNo as Long ' 訂位號碼

' 存上筆資料作為欄位預設值
Private Sub Form_AfterInsert()
  OrderDate = Me.日期
  MachID = Me.機台
  OrderNo = Me.訂位號碼
End Sub

'
將欄位預設值放入準備 key-in 的新筆資料欄位
Private Sub Form_BeforeInsert()
  Me.日期 = OrderDate
  Me.機台 = MachID
  Me.訂位號碼 = OrderNo
End Sub

使用 VB6 在同一個 Form 上如何切換資料?


問題:


請問使用 VB6 如何在同一個 Form 上切換資料?我有客戶的基本資料、售價資料和會計資料需用三個按鍵來作切換,例如按「售價資料」會顯示客戶售價的欄位資料並且隱藏其他資料,會計資料鍵則顯示會計的欄位資料而隱藏其他資料, 請問要如何做?

如果要將
售價資料和會計資料放在個別子視窗上,又應該怎麼做?


回答:

如果只用一個 Form 來處理,你可以將三種會變動的資料欄位放在三個 Frame 裡,按下其中一個資料鍵時,將對應的 Frame 顯示並隱藏其他兩個 Frame。譬如說按下基本資料鍵時,將含有基本資料的 Frame 顯示出來,並將含有售價資料和會計資料的兩個 Frame 隱藏起來。

如果要用一個主視窗和兩個子視窗來控制,你可以將客戶基本資料放在一個 Form 上,並且用個按鍵來切換顯示售價資料和會計資料,然後用客戶編號來關聯要切換的三種資料,當按下切換鍵時就必須把客戶編號傳給子視窗來讀取資料,客戶編號可以使用全域變數儲存讓所有的 Form 共用,也可以寫一個全域函數當作功能的主控台,讓客戶基本資料這個 Form 能以客戶編號呼叫它。

Access 主表單與子表單如何互相傳值?


問題:


我有一個「訂單」主表單和兩個子表單訂單明細」與存貨交易」,在自動傳值上遇到困難,請問下列狀況我該如何處理?

1. 主表單訂單.orderID要在輸入後傳至子表單存貨交易.PurchaseOrderID
2. 子表單訂單明細.ProductID要在輸入後傳至子表單存貨交易.ProductID
3. 子表單訂單明細.Quantity要在輸入後傳至子表單存貨交易.UnitsOrdered

可以提供 VBA 的寫法嗎?


回答:

首先你要確立表單之間的關聯性:

1. 「訂單」的主鍵為 OrderID,訂單明細也需要一個 OrderID 的欄位與 「訂單」 作關聯,並且以 OrderID 和 ProductID 作為主鍵。

2. 存貨交易以 PurchaseOrderID 和 ProductID 作為主鍵,並以這兩個欄位與訂單明細的 OrderID 和 ProductID 作關聯。

資料的關聯性確立之後就容易了,其實這個關聯性可以透過 Access 的資料庫關聯圖來建立,並且能夠減少 VBA 的控制,不過這裡我先完全以 VBA 來控制。

首先建立一個以「訂單」為資料來源的主表單,然後在這個表單內建立兩個子表單,分別以訂單明細存貨交易為資料來源。

接 下來就是作表單間的關聯,在訂單明細子表單的屬性表資料頁籤裡設定連結主欄位與子欄位為 OrderID,在存貨交易子表單的屬性表資料頁籤裡設定連結主欄位為訂單明細.OrderID訂單明細.ProductID,設定連結子欄位為存貨交易.PurchaseOrderID存貨交易.ProductID

做好上面的資料關聯後,當你在子表單輸入資料時就會自動把連結主欄位的資料帶入。不過你的 存貨交易資料似乎要自動新增,而修改訂單明細.Quantity時也要更新到存貨交易.UnitsOrdered,這個地方還是要靠 VBA 來控制。

如果上面的資料關聯性沒有問題的話,請你先確定訂單明細子表單是一個獨立的表單,在 「訂單」主表單裡頭是用一個子表單控制項去連結它。

接下來就是用 VBA 來控制自動新增及修改存貨交易資料,請開啟訂單明細子表單並將 Visual Basic 的程式編輯視窗打開,確定一下程式碼視窗標題是你要編輯程式的表單名稱,也就訂單明細

以上操作程序都沒有問題的話,請將下列程式碼複製到剛剛的程式編輯視窗:

' 自動新增存貨交易資料
Private Sub Form_AfterInsert()
  Dim sSQL As String

 sSQL = "insert into 存貨交易 values(" & 訂單明細.OrderID & ", " & 訂單明細.ProductID & ", " & 訂單明細.Quantity & ")"

  DoCmd.RunSQL sSQL
End Sub

' 自動修改存貨交易資料

Private Sub Form_AfterUpdate()
  Dim sSQL As String

 sSQL = "update 存貨交易 set UnitsOrdered = " & 訂單明細.Quantity & _
   " where PurchaseOrderID = " & 訂單明細.OrderID & " and ProductID = " & 訂單明細.ProductID

  DoCmd.RunSQL sSQL
End Sub

上述的 SQL 語法必須依你實際定義的存貨交易資料欄位名稱、型態、順序等加以調整,這裡只是一個程式範本,主要是讓你瞭解程式的控制點在哪些事件程序

2008-04-28

VB ~ 每秒抓 BUFF 的資料做曲線圖


問題:


我想用 TIMER 每秒抓 BUFF 資料五百筆來畫出曲線圖 (像心電圖一樣讓曲線一直往左移動),
時間為 X 軸,收到的資料為 Y 軸,請問要怎麼做才能讓曲線向左移動?


回答:

一般的作法就是在 PictureBox 裡面再用 PictureBox,外面的 PictureBox 當作固定的顯示範圍,就好比是儀器的顯示幕,而裡面的 PictureBox 才是繪圖板,這樣你就可以控制內部 PictureBox 的位置 (PictureBox.Left) 來作左移的效果。

內 部 PictureBox 的寬度是考量的重點,必須配合 Timer 的時間間隔、三分鐘的資料以及 X 軸的單位長度來設定。譬如說每秒抓 500 點的資料,三分鐘就有 90,000 點資料,但是 PictureBox.Width 好像不能設得這麼大,顯然用一個 PictureBox 是不夠儲存三分鐘的資料。所以如果一個 PictureBox 儲存 30,000 點資料,就需要三個 PictureBox,也就是說用三個 PictureBox 左右頭尾相接來畫三分鐘的資料。

接著要讓曲線可以自動向左移動,以前面的例子來說,就是在 Timer 的事件中移動這三個 PictureBox,每秒各移動 500 點。另外你必須用一個水平捲軸來控制使用者的捲動,但是這裡你會發現一個問題,如果某一時間三分鐘的資料頭在第一個 PictureBox 的第一點,而資料尾在第三個 PictureBox 的最後一點,那麼下一秒必須捨棄第一個 PictureBox 的前 500 點,然後把最新的 500 點資料畫在最右側,但是第三個 PictureBox 已經畫滿了,而第一個 PictureBox 仍然必須保留在最左側以備查看,所以事實上需要用第四個 PictureBox 來處理這個狀況。在第一個 PictureBox 的資料完全被捨棄後,就要把它調到最右側變成第四個來承接新進的資料。

基本上就是用這樣的方式來循環控制,僅提供你程式寫作的方法,我想程式本身還是要靠自己去寫去試,這樣將來你才有能力知道如何去調整加強它的功能。

Access 裡用 MID 切割中英文的問題


問題:


我在 ACCESS 裡面對一個文字檔用 MID 切割資料並且要存入 Table 中,但是這個文字檔是中英文混雜的,例如其中一行資料是

ABCDEFG中文描述1234567台灣BABYG股份有限公司EXAMPLE

我想要切割成:

ABCDEFG ==> 欄位一 ( 寬度 7 bytes )
中文描述 ==> 欄位二 ( 寬度 8 bytes )
1234567 ==>欄位三 ( 寬度 7 bytes )
台灣BABYG股份有限公司 ==> 欄位四 ( 寬度 21 bytes )
EXAMPLE ==> 欄位五

但是問題發生了,以 "台灣BABYG股份有限公司" 這個部份來看,因為中文字是 double bytes,所以它在文字檔的位置應該是在 23 (7 + 8 + 7 + 1),寬度 21,也就是說應該用 MID(23,21) 來切取,但實際切取的結果卻是 "BYG股份有限公司EXAMPLE",所以變成要用 MID(19.13) 才會正確。MID 函數似乎把 double bytes 的中文算成 single byte,讓我在讀取大量不規則中英文混合的資料上有很大的困擾,不知道有沒有什麼解決之道。

請求協助,謝謝!


回答:

首先必須確定文字檔內的資料欄位都是固定寬度,在使用傳統的 ASCII Code 時,英數字為 1 byte,中文為 2 bytes,但若使用 Unicode,中英文皆為 2 bytes。

在 VBA 程式裡是以 Unicode 處理字串,Mid 函數是以字元的角度來切割字串,不管字元是用 1 個或 2 個 byte 儲存,MidB 函數才是用 byte 來切割字串。

所以你的文字檔和程式的處理方式必須要配合,先弄清楚你的文字檔是用 ASCII Code 還是 Unicode 儲存,如果是 ASCII Code,在讀入整列資料後,要用MidB 函數來切割欄位。

VB 6.0 作業不會打請求程式碼


問題:


輸入四個任意數並且求其最大和最小值,請求給予程式碼。
另外應該要用什麼樣的屬性視窗,希望越詳細越好。

謝謝~~


回答:

Dim i
Dim Result As String
Dim Num, Max, Min As Variant

' 輸入四個任意數並儲存最大和最小值
i = 1
Do While i <= 4
 Num = InputBox("請輸入第 " & Cstr(i) & " 個數")

 If IsNumeric(Num) Then
  If i = 1 Then
   Max = Num
   Min = Num
  ElseIf Num > Max
   Max = Num
  ElseIf Num <>
   Min = Num
  End If

  If Result <> "" Then Result = Result & ", "
  Result = Result & Cstr(Num)
  i = i + 1
 End If
Loop

' 輸出結果
Result = Result & " 四個數之最大值為 " & Cstr (Max) & ", 最小值為 " & Cstr(Min)
MsgBox Result


P.S.使用一般的視窗就可以,在視窗中加一個命令鍵,並把上面的程式複製到這個命令鍵的 Click 事件程序中。

如何將產品依數量遞減排序?


問題:


我有三個 CheckBox,分別為三種產品的核取選項,勾選時會自動累計該產品數量,按 CommandButton 後會將三種產品依數量遞減排序,並顯示於 Label 上。

Ex: 產品 A = 5, 產品 B = 4, 產品 C = 3

請問程式應該怎麼寫?


回答:

假設產品名稱及數量存放在以下陣列變數裡:
Dim ProdName(2) As String
Dim ProdQty(2) As Long

請在 CommandButton 的 Click 事件程序裡加入以下程式碼:

Private Sub Command1_Click()
 Dim ProdRank(2) As Integer, TmpRank As Integer
 Dim i, j As Integer

 ' ProdRank 存放的是產品的索引位置,一開始設定它們的數量排名順序和索引位置相同
 For i = 0 to 2
  ProdRank(i) = i
 Next

 ' 再依照產品實際的數量逐一調整它們的順序
 For i = 0 to 1
  For j = i 1 To 2
   If ProdQty(ProdRank(i)) <>
    TmpRank = ProdRank(i)
    ProdRank(i) = ProdRank(j)
    ProdRank(j) = TmpRank
   End If
  Next
 Next

 ' 將排序結果以 Label1 顯示
 Label1 = ""
 For i = 0 to 2
  Label1 = Label1 & ProdName(ProdRank(i)) & " = " & Cstr(ProdQty(ProdRank(i))) & vbCrlf
 Next
End Sub

2008-03-01

藍城簡介


服務理念:


服務理念


服務範圍

服務範圍


未來願景

未來願景

藍鳥任務


服務項目:


服務項目


服務流程:

服務流程

藍城經濟


收費項目:


收費項目


收費說明:

收費說明