1

假设我有一个表“PersonData”,其中 4 列是

FromPersonId、FromEmployeeId、ToPersonId、ToEmployeeId

任何记录只包含 Only 一个 From** 和 Only 一个 To** 并且其他两列为空。也属于“Person”表,并且FromPersonId属于“Employee”表。ToPersonIdFromEmployeeIdToEmployeeId

我的问题是:如何正确地将 PersonData 与 Person 和 Employee 表连接起来?

请注意,我尝试了很多不同的方法,但是当我对 PersonData 进行计数时,我在进行连接时会得到不同的结果(即它显示的内容比 PersonData 中的更多)...

我应该如何加入?我应该为每个 FromPersonId 和 ToPersonId 做一个到 Person 并为 Employee 做类似的事情吗?(怀疑是这种情况)...

谢谢,

巫毒教

4

3 回答 3

2

看起来有 4 种可能性:
FromPerson -> ToPerson
FromPerson -> ToEmployee
FromEmployee -> ToPerson
FromEmployee -> ToEmployee

所以,我建议加入 4 个查询并合并结果。类似的东西(假设您出于示例的目的在 from 和 to 名称之后):

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)

于 2010-06-29T07:16:44.357 回答
1

好的,听起来问题是如果您在 FromPersonID=PersonID 和 ToPersonId=PersonID 上加入 Person,您会为 PersonData 中的每条记录获得 2 条记录。

解决此问题的方法是加入到 PersonData 的 2 个别名副本,以便您可以将结果附加到同一行。就像是:

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

基本上对 to 和 from 员工字段做同样的事情

于 2010-06-29T07:23:00.167 回答
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能够的​​列意味着我们不能有 aPRIMARY KEY但我想知道是否有钥匙......?

我们只需要一种类型的 ID 分别用于 'from' 和 'to':

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 呢?

如果员工不是人,您可以发布您的架构(数据类型、约束等)吗?

于 2010-06-29T13:53:07.223 回答