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