1

对具有多个一对多关系的 1 个表进行建模的最佳方法是什么。

在此处输入图像描述

使用上述模式,如果 Report 包含 1 行,Grant 2 行和 Donation 12。当我将这三者连接在一起时,我最终得到一个笛卡尔积和 24 的结果集。 Report 加入 Grant 并创建 2 行,然后 Donation 加入该行做24行。

有没有更好的方法来模拟这个以避免caresian product?

示例代码

DECLARE @Report
TABLE   (
        ReportID    INT,
        Name        VARCHAR(50)
        )

INSERT
INTO    @Report 
        (
        ReportID,
        Name 
        )

SELECT  1,'Report1'


DECLARE @Grant 
TABLE   (
        GrantID     INT IDENTITY(1,1) PRIMARY KEY(GrantID),
        GrantMaker  VARCHAR(50),
        Amount      DECIMAL(10,2),
        ReportID    INT
        )

INSERT
INTO    @Grant 
        (
        GrantMaker,
        Amount,
        ReportID
        )

SELECT  'Grantmaker1',10,1
UNION ALL
SELECT  'Grantmaker2',999,1


DECLARE @Donation
TABLE   (
        DonationID      INT IDENTITY(1,1) PRIMARY KEY(DonationID),
        DonationMaker   VARCHAR(50),
        Amount          DECIMAL(10,2),
        ReportID        INT
        )

INSERT
INTO    @Donation 
        (
        DonationMaker,
        Amount,
        ReportID
        )

SELECT  'Grantmaker1',10,1
UNION ALL
SELECT  'Grantmaker2',3434,1
UNION ALL
SELECT  'Grantmaker3',45645,1
UNION ALL
SELECT  'Grantmaker4',3,1
UNION ALL
SELECT  'Grantmaker5',34,1
UNION ALL
SELECT  'Grantmaker6',23,1
UNION ALL
SELECT  'Grantmaker7',67,1
UNION ALL
SELECT  'Grantmaker8',78,1
UNION ALL
SELECT  'Grantmaker9',98,1
UNION ALL
SELECT  'Grantmaker10',43,1
UNION ALL
SELECT  'Grantmaker11',107,1
UNION ALL
SELECT  'Grantmaker12',111,1

SELECT  *
FROM    @Report r
INNER JOIN
        @Grant g
        ON  r.ReportID = g.ReportID 
INNER JOIN
        @Donation d
        ON  r.ReportID = d.ReportID 

更新 1 2011-03-07 15:20

为到目前为止的反馈干杯,为了添加到这个场景中,还有 15 个其他的一对多关系来自一个报告表。由于各种业务原因,这些表不能组合在一起。

4

3 回答 3

2

赠款和捐赠之间有任何关系吗?如果没有,撤回显示它们之间的伪关系的查询是否有意义?

我会做一个赠款查询:

SELECT r.*, g.*
FROM @Report r
JOIN @Grant g ON r.ReportID = g.ReportID

还有一个捐款:

SELECT r.*, d.*
FROM @Report r
JOIN @Donation d ON r.ReportID = d.ReportID

然后让您的应用程序显示适当的数据。

但是,如果 Grants 和 Donations 相似,则只需制作一个更通用的表,例如 Contributions。

Contributions
-------------
ContributionID (PK)
Maker
Amount
Type
ReportID (FK)

现在您的查询是:

SELECT r.*, c.*
FROM @Report r
JOIN @Contribution c ON r.ReportID = c.ReportID
WHERE c.Type = 'Grant' -- or Donation, depending on the application
于 2011-03-07T15:16:19.767 回答
1

如果您要加入 ReportID,那么不,您无法避免很多行。当您省略“报告”表,并在 ReportId 上将“捐赠”连接到“授予”时,您仍然会得到 24 行。

SELECT  *
FROM    Grant g
INNER JOIN
        Donation d
        ON  g.ReportID = d.ReportID 

但关键是,在现实世界中匹配捐赠和赠款是没有意义的。它们是完全独立的事物,本质上彼此无关。

在数据库中,上面的语句会将 Grants 中的每一行连接到 Donation 中的每个匹配行。生成的 24 行真的不应该让您感到惊讶。

当您需要向用户呈现独立的事物时,您应该使用独立选择独立事物的报告编写器或 Web 应用程序(例如)。选择捐赠并将其放入报告或网页的一个部分,然后选择赠款并将放入报告或网页的另一部分,依此类推。

如果表“报告”应该帮助您记录哪些部分进入特定报告,那么您需要一个更像这样的结构:

create table reports (
    reportid integer primary key,
    report_name varchar(35) not null unique
);

create table report_sections (
    reportid integer not null references reports (reportid),
    section_name varchar(35),  -- Might want to reference a table of section names
    section_order integer not null,
    primary key (reportid, section_name)
);
于 2011-03-07T16:15:12.700 回答
0

捐赠和赠款表看起来几乎相同。您可以将它们设为一张表并添加类似于 DonationType 的列。将复杂性降低 1 个表。现在,如果捐赠和赠款完全不同并且具有与之关联的不同子表,那么将它们分开并且一次只加入一个将是理想的。

于 2011-03-07T15:14:16.457 回答