2010-06-29 40 views
1

比方說,如果我有一個表「PersonData」在其列4sql查詢幫助 - 如何正確加入?

FromPersonId,FromEmployeeId,ToPersonId,ToEmployeeId

任何的記錄,只有永遠只包含一個從**和唯一一個**和另外兩列是空的。 FromPersonIdToPersonId屬於「Person」表,FromEmployeeIdToEmployeeId屬於「Employee」表。

我的問題是:如何正確地將PersonData與Person和Employee表連接起來?

請注意,我已經嘗試了一堆不同的方法,但是當我做了PersonData計數做一個連接(即,它顯示出比什麼是在PersonData以上)時,我得到不同的結果...

我應該怎麼做一個加入?我應該爲每個FromPersonId和ToPersonId對Person執行一個操作並且爲Employee執行類似操作? (懷疑這是事實)...

感謝,

巫毒

+0

如果您對「正確」做事感興趣 - 您的表格結構有異味(或者我不明白您在做什麼)。這似乎應該是一個簡單的兩列關聯表,具有PersonID和EmployeeID。空列有什麼意義? – harpo 2010-06-29 06:59:40

+0

@Harpo這是一箇舊的應用程序,我正在遷移的數據,它是這樣做回來像10-15年前... – VoodooChild 2010-06-29 07:05:04

+1

爲什麼獲得更多的結果比PersonData中的結果不正確?如果您具有FromPersonID和ToPersonID的值,那麼您的加入將匹配Person表中的2條記錄。 – 2010-06-29 07:10:05

回答

1

好了,這聽起來像問題是,如果你加入到人上FromPersonID =是PersonID和ToPersonId = PersonID,您將獲得PersonData中每條記錄的2條記錄。

解決方法是加入PersonData的兩個別名副本,以便將結果附加到同一行中。喜歡的東西:

Select * from PersonData 
LEFT JOIN Person p1 on p1.PersonID = FromPersonID 
LEFT JOIN Person p2 on p2.PersonID = ToPersonID 

,基本上做同樣的,並從員工的領域

+0

F $#@##左加入是答案....你真棒:) – VoodooChild 2010-06-29 07:27:12

+0

此外,羅布,不同類型的聯接之間的差異,這將有助於我的一些不錯的指南,不難遵循的東西:)再次感謝。 – VoodooChild 2010-06-29 07:29:42

+1

np :)我認爲關於連接的主要事情只是一個內部連接將只返回兩個表中的結果,其中外部連接將返回來自統治表的所有行以及不匹配的字段的空值記錄在另一張表中。如果不指定,則內部連接默認完成。左連接是一個外連接,它只是說明支配表是第一個指定的表。想象一下,你有來自PersonData的字段值坐在左邊,然後我們只是「螺栓」p1值,如果它們存在。現在這個組合是新的左邊,我們「栓上」任何p2值。 – 2010-06-29 07:37:38

2

它看起來像有4種可能性:
從FROMPERSON - > TOPERSON
從FROMPERSON - > ToEmployee
FromEmployee - > ToPerson
FromEmployee - > ToEmployee

所以,我建議加入4個查詢和聯合結果。喜歡的東西(假設你是從,併爲示例的目的名之後):

SELECT from.name from_name, to.name to_name
FROM Person from, PersonData pd, Person to
WHERE from.Id = pd.FromPersonId
AND to.Id = pd.ToPersonId
UNION
SELECT from.name from_name, to.name to_name
FROM Person from, PersonData pd, Employee to
WHERE from.Id = pd.FromPersonId
AND to.Id = pd.ToEmployeeId
UNION
... (you get the picture)

+0

我的表格大於25列,我需要幾乎所有的數據,除聯合之外還有其他方法嗎?有沒有一種方法可以將Person和Employee明確地加入PersonData。 – VoodooChild 2010-06-29 07:24:15

1

因爲你沒有張貼您模式作爲SQL DDL,我在看到這些表是如何工作的問題實踐。這裏是我的嘗試:

這似乎是一個合理的假設一個僱員必須是一個人,所以這是很容易的(猜測數據類型和域規則):

CREATE TABLE NaturalPersons 
(
PersonId INTEGER NOT NULL UNIQUE 
); 

CREATE TABLE Employees 
(
PersonId INTEGER NOT NULL UNIQUE 
    REFERENCES NaturalPersons (PersonId), 
EmployeeID CHAR(3) NOT NULL UNIQUE 
    CHECK (EmployeeID LIKE '[A-Z][0-9][0-9]') 
); 

表名「PersonData」沒有按」牛逼透露太多,但是從數據元素的名稱似乎有些事情是從一個人/員工轉移到另一個:

CREATE TABLE Transfers 
(
FromPersonId INTEGER 
    REFERENCES NaturalPersons (PersonId), 
FromEmployeeID CHAR(3) 
    REFERENCES Employees (EmployeeID), 
ToPersonId INTEGER 
    REFERENCES NaturalPersons (PersonId), 
ToEmployeeID CHAR(3) 
    REFERENCES Employees (EmployeeID) 
); 

嗯,所有NULL能夠列意味着我們不能有一個PRIMARY KEY,但我不知道是否有一個關鍵... ...?

我們只想要一個ID類型爲「從」和「爲」:

ALTER TABLE Transfers ADD 
CONSTRAINT only_one_from_ID 
    CHECK (
      (FromPersonId IS NULL AND FromEmployeeID IS NOT NULL) 
      OR 
      (FromPersonId IS NOT NULL AND FromEmployeeID IS NULL) 
     ); 

ALTER TABLE Transfers ADD 
CONSTRAINT only_one_to_ID 
    CHECK (
      (ToPersonId IS NULL AND ToEmployeeID IS NOT NULL) 
      OR 
      (ToPersonId IS NOT NULL AND ToEmployeeID IS NULL) 
     ); 

我們也會希望有一個「常識」的業務規則,以防止傳輸往返於同一個人/員工:

ALTER TABLE Transfers ADD 
CONSTRAINT FromPersonId_cannot_be_ToPersonId 
    CHECK (FromPersonId <> ToPersonId); 

ALTER TABLE Transfers ADD 
CONSTRAINT FromEmployeeId_cannot_be_ToEmployeeId 
    CHECK (FromEmployeeId <> ToEmployeeId); 

這是對我們能做的最好的,但是我們有幾個問題:

INSERT INTO NaturalPersons (PersonId) VALUES (1), (2), (3), (4); 
INSERT INTO Employees (PersonId, EmployeeID) VALUES (1, 'A11'), (2, 'B22'); 

-- transfer to same entity - oops!: 
INSERT INTO Transfers (FromPersonId, ToEmployeeID) VALUES (1, 'A11'); 

-- Duplicate transfer - oops!: 
INSERT INTO Transfers (FromEmployeeId, ToPersonID) VALUES (1, 'B1'); -- duplicate 
INSERT INTO Transfers (FromPersonId, ToEmployeeID) VALUES ('A1', 2); -- duplicate 

換句話說,將PersonId和EmployeeID混合在同一個表中使得編寫基本數據規則變得困難。

如果我正確地假設僱員是一個人,爲什麼不只是使用PersonID?

如果員工不是一個人,您可以發佈您的模式(數據類型,約束等)嗎?

+0

非常感謝和+1,我希望以後會詳細閱讀。但我的問題只是一個例子,並沒有真正涉及人員或員工 - 我需要做一些與其他一些舊應用程序數據類似的事情,但是正在繪製一個完整的空白... – VoodooChild 2010-06-29 14:26:07