2010-07-07 55 views
3

我們有一個運動訓練營,經常有城市的各個團隊參加。我們每天都有一場會議,時間跨度爲2小時(上午9-11點),而且不同團隊的時段可能會有所不同。我們想每天捕捉參加訓練營的人員。什麼是優化模式以獲取考勤數據的最佳方式

我們到了以下模型以捕捉出席。 (id,user_id,date,present)。假設用戶每天都參加露營(比如說一個月內30天),那麼您會在數據庫中看到很多記錄。

假設我們只是想知道用戶參加陣營的天數,有沒有更好的方法來標記是否存在特定的用戶(也許只有一個月的一個行,並標記所有(P,P,P,A,...,A,P)P =當前,A =缺席

回答

1
AttMst 
    id | date 

AttDet 
    attdetid | id | userid 

通過這種方式,您需要將日期存儲在AttMst中,當天的用戶將存儲在AttDet中。

+0

正在轉向這種模式。你如何查詢一個月的所有用戶出勤記錄?你將如何加入AttMst表? – Sam 2010-07-07 09:24:03

+1

'select date,userid from AttMst am,AttDet ad where am.id = ad.id group by date'這將顯示日期現在的用戶。但它是未經測試的查詢請檢查它。 – Himadri 2010-07-07 09:39:42

0

恕我直言,每個用戶每月有一個單行與大量連接字符不會比擁有大量帶有單個字符的行更好,尤其是當您要在每次想要在另一個應用程序上顯示數據時分割該字符串。

如果你只是想弄清楚數量用戶參加你的營地的日子,爲什麼不專門爲此創建一個表格?每次您記錄用戶出席時,您只需通過增加用戶參加的天數來更新該表。因此,這個值不會被即時計算,它不應該給你任何性能問題。

所以,我的建議將包括兩個表:

id | user_id | date | present 

user_id | month | attendance 

您應該對USER_ID領域的一些指標還有,爲了提高系統的性能。

乾杯

+0

假設次表將用於每當被標記時遞增或遞減。所以你建議不要用數字(*)機制來達到玩家在場的總天數。我對麼? – Sam 2010-07-07 09:36:06

+1

是的,主要是因爲它可能會導致性能問題。但是,如果你有一個快速的服務器或不期望大量的用戶,那麼計數機制是好的。 無論哪種方式,忘記串接。 – 2010-07-07 10:05:37

2

你應該問自己,爲什麼你會那樣做。

有一些可能性,但很可能您的數據庫架構不會完全標準化。

所以首先:你想達到什麼目的?這是什麼原因?

一些可能性:

  • 一些DBMS提供能力 創建用戶定義類型
  • 你可以使用按位的方法(在MySQL最簡單的方法是使用the SET datatype

但是,您目前遇到的問題是什麼,因爲找出某人出席的天數只不過是加入適當的表格,並與計數函數聚合在一起

+0

我同意,一張桌子就夠了。數據庫服務器速度很快,所以不需要非規範化。 – mb14 2010-07-07 09:22:35

+0

@ mb14但是當數據量很大時,對數據進行歸一化將會有所幫助。 – Himadri 2010-07-07 09:28:33

+0

我不確定我們是否需要很多行來捕獲考勤信息(如果您查看帶有此類信息的Excel表,它就像一個網格,並且您有一整個月對用戶的值,一天中的所有天月)。我試圖模擬這一點。我同意這樣一個事實,即在逗號分隔列表中標記是否存在玩家會很痛苦 – Sam 2010-07-07 09:32:45

2

您在問題標題中使用「優化」一詞,而不解釋您想優化什麼

如果你在談論查詢性能,那麼你沒有問題。您可以擁有的記錄數由您每天的會話數決定(因爲只有一個團隊可以參加任何特定會話)。如果你每天運行十個會話,每月有三百個記錄。如果每天運行一百次,每月有三千條記錄。這些數據量不大。因此,您通過歪曲數據庫設計來做出一個糟糕的決定,以避免出現不存在的性能問題。

您在其中一條評論中提到了電子表格。這不是一個糟糕的設計。沿着第一排有一些會議,一邊是團隊,另一邊是細胞顯示一個團隊是否出席了會議。這些映射到三個數據庫表:SESSIONS,TEAMS和相交表TEAM_SESSIONS。團隊出席會議時,您只需要TEAM_SESSIONS中的記錄。

作爲一個概念證明,我在Oracle中敲了三張表。

SQL> desc teams 
Name          Null? Type 
----------------------------------------- -------- ---------------------------- 
ID          NOT NULL NUMBER 
NAME            VARCHAR2(20 CHAR) 

SQL> desc sessions 
Name          Null? Type 
----------------------------------------- -------- ---------------------------- 
ID          NOT NULL NUMBER 
SSN_DAY           DATE 
SSN_START           NUMBER(4,2) 
SSN_END           NUMBER(4,2) 

SQL> desc team_sessions 
Name          Null? Type 
----------------------------------------- -------- ---------------------------- 
TEAM_ID         NOT NULL NUMBER 
SESSION_ID        NOT NULL NUMBER 

SQL> 

在Oracle 11g中引入的PIVOT功能使它成爲不在話下敲了一個矩陣(DBMS的不同口味都會有不同的方法可以解決這個)。正如你所看到的,今天有三支球隊已經預定了會議,沒有人希望在午餐時間訓練,並且Bec United非常熱衷於芥末(或者需要訓練)!

SQL> select * from (
    2  select t.name as team_name 
    3    , trim(to_char(s.ssn_start))||'-'||trim(to_char(s.ssn_end)) as ssn 
    4    , case when ts.team_id is not null then 1 else 0 end as present 
    5  from sessions s 
    6    cross join teams t 
    7    left outer join team_sessions ts 
    8     on (ts.team_id = t.id 
    9      and ts.session_id = s.id) 
10  where s.ssn_day = trunc(sysdate) 
11  ) 
12 pivot 
13  (sum (present) 
14  for ssn in ('9-11', '11-13', '13-15', '15-17', '17-19') 
15  ) 
16 order by team_name 
17/

TEAM_NAME    '9-11' '11-13' '13-15' '15-17' '17-19' 
-------------------- ---------- ---------- ---------- ---------- ---------- 
Balham Blazers    0   1   0   0   0 
Bec United     1   0   0   0   1 
Dinamo Tooting    0   0   0   0   0 
Melchester Rovers    0   0   0   1   0 

SQL> 

無論如何,這個數據模型的優點在於它是靈活的。我們可以統計一個團隊參加的頻率,他們參加的次數,他們參加的一週中的哪一天,總是預定什麼會話,什麼會議很少預訂等等。另外,管理數據很容易。特別是,三表解決方案優於兩個表格的優點是,防止重複預訂和非標準或重疊時隙更容易。

你看,規範化不僅僅是一些我們用來詛咒無辜的月亮語言,它提供了真正的實際好處。有少數情況下駕車至少BCNF不是最好的主意。

相關問題