2009-09-11 34 views
2

我有3個不同的事務表,它們看起來非常相似,但略有不同。這是因爲有3種不同的交易類型。取決於交易類型的列更改,所以爲了讓他們在3NF我需要在單獨的表中(右?)。超過3個表的棘手的SQL語句

舉個例子:
T1: 日期,用戶量

T2: 日期,用戶,誰,量

T3: 日期,用戶,內容,金額

現在我需要一個查詢誰將會讓我在同一個用戶的每個表中的所有交易,如

select * from t1,t2,t3 where user ='me'; (這當然不起作用)。

我正在學習JOIN語句,但還沒有找到正確的方法來做到這一點。謝謝。

編輯:其實我需要那麼從每個表中的所有列,不只是誰是相同的。編輯#2:是的,有transaction_type不會打破3NF,當然 - 所以也許我的設計是完全錯誤的。這是真正發生的事情(這是一個替代貨幣系統):
- 交易是在用戶之間進行的,例如互信。所以單位在用戶之間交換。
- 發明物是帶入系統的物理材料;一個用戶得到這個單位。
- 消費是物質消耗;用戶必須爲此支付單位。

 
|--------------------------------------------------------------------------| 
| type  | transactions  | inventarizations | consumations  | 
|--------------------------------------------------------------------------| 
| columns | date    | date    | date    | 
|   | creditor(FK user) | creditor(FK user) |     | 
|   | debitor(FK user) |     | debitor(FK user) | 
|   | service(FK service)|     |     | 
|   |      | asset(FK asset) | asset(FK asset) | 
|   | amount    | amount   | amount   | 
|   |      |     | price   | 
|--------------------------------------------------------------------------| 

(注意「量」是在不同的單元;這些是條目和計算上的那些量外製成的範圍來解釋爲什麼,但這些是字段)。
因此,問題變成「可以/應該在一個表格中還是多個表格(就像我現在所擁有的那樣)?」 我需要先前描述的SQL語句來顯示運行餘額。


(這個現在應該成爲一個新的問題,還是可以編輯?)。

編輯#3:由於編輯#2實際上將此轉換爲新問題,我還決定發佈a new question。 (我希望這是好的?)。

回答

5

您可以在select語句中爲沒有數據的列提供默認值作爲常量;

所以

SELECT Date, User, Amount, 'NotApplicable' as Who, 'NotApplicable' as What from t1 where user = 'me' 
UNION 
SELECT Date, User, Amount, Who, 'NotApplicable' from t2 where user = 'me' 
UNION 
SELECT Date, User, Amount, 'NotApplicable', What from t3 where user = 'me' 

即假設誰和什麼是字符串類型的列。您也可以使用Null,但需要某種佔位符。

我認爲將您的附加信息放在單獨的表格中,並將所有交易記錄在單個表格中,但對於您來說,除非有其他詳細信息,否則這些信息會更好。

+0

NULL作爲列佔位符更安全,因爲如果存在值,則列輸出必須是相同的數據類型。 – 2009-09-12 02:58:51

+0

我應用了這種方法,它迄今爲止工作正常。現在我嘗試了一個帶有transaction_type的「master」事務表,它引用了3個獨立表中的附加信息。我懷疑它,但可以通過設置一個外鍵取決於transaction_type並因此指向3個表中的一個來獲得引用完整性嗎? – faboolous 2009-09-13 10:48:48

0

你應該考慮STI「架構」(單表繼承)。即將所有不同的列放在一個表中,並將它們全部放在一個索引下。

另外,您可能需要將索引添加到其他正在進行選擇的列中。

0

結果模式將會是什麼樣子? - 如果你只是想最少列是在所有3個表,那麼它很容易,你只需UNION結果:

SELECT Date, User, Amount from t1 where user = 'me' 
UNION 
SELECT Date, User, Amount from t2 where user = 'me' 
UNION 
SELECT Date, User, Amount from t3 where user = 'me' 
+2

請考慮UNION ALL,而不是 – nos 2009-09-11 20:40:27

+0

是的,沒有ALL的UNION是潛在的SQL最昂貴的語句。 – 2009-09-11 20:44:36

0

,或者你可以「子類」他們

Create Table Transaction 
    ( 
    TransactionId Integer Primary Key Not Null, 
    TransactionDateTime dateTime Not Null, 
    TransactionType Integer Not Null, 
    -- Othe columns all transactions Share 
) 

    Create Table Type1Transactions 
    { 
    TransactionId Integer PrimaryKey Not Null, 
    // Type 1 specific columns 
    } 
    ALTER TABLE Type1Transactions WITH CHECK ADD CONSTRAINT 
    [FK_Type1Transaction_Transaction] FOREIGN KEY([TransactionId]) 
    REFERENCES [Transaction] ([TransactionId]) 

其他重複交易類型...

1

我覺得你的問題的肉是在這裏:

取決於交易類型的列發生變化,因此讓他們在3NF我需要讓他們在不同的表(右?)。

我不是3NF的專家,但我會以不同的方式處理你的模式(這可能會清理你的SQL)。

它看起來像你的數據元素是這樣:日期用戶,並什麼。考慮到這一點,更規範化的模式可能是這個樣子:

 
User 
---- 
id, user info (username, etc) 

Who 
--- 
id, who info 

What 
---- 
id, what info 

Transaction 
----------- 
id, date, amount, user_id, who_id, what_id 

你的外鍵約束的措辭會根據數據庫實現,但這是一個更清晰一點(和擴展)。

0

簡單地將不需要的列留空並添加一個TransactionType列呢?這將導致一個簡單的SELECT語句。

-1
select * 
from (
    select user from t1 
    union 
    select user from t2 
    union 
    select user from t3 
) u 
left outer join t1 on u.user=t1.user 
left outer join t2 on u.user=t2.user 
left outer join t3 on u.user=t3.user