Проектирование базы данных - множественные отношения 1 ко многим - PullRequest
1 голос
/ 07 марта 2011

Что было бы лучшим способом смоделировать таблицу 1 с несколькими отношениями 1 ко многим.

enter image description here

С помощью приведенной выше схемы, если Отчет содержит 1 строку, Грант 2 строки и Пожертвование 12. Когда я объединяю эти три вместе, я получаю декартово произведение и набор результатов 24. Отчет соединяется с Грантом и создает 2 строки, затем Донор присоединяется к тому, чтобы сделать 24 ряда.

Есть ли лучший способ смоделировать это, чтобы избежать марихуаны?

пример кода

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 взаимосвязей 1 ко многим из одной таблицы отчета. Эти таблицы не могут быть сгруппированы по разным причинам.

Ответы [ 3 ]

2 голосов
/ 07 марта 2011

Есть ли какая-либо связь между грантами и пожертвованиями?Если нет, имеет ли смысл отозвать запрос, который показывает псевдосвязь между ними?

Я бы сделал один запрос для грантов:

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

Затем пусть ваше приложение покажет соответствующие данные.

Однако, если гранты и пожертвования похожи, просто создайте более общую таблицу, такую ​​как Взносы.

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
1 голос
/ 07 марта 2011

Если вы собираетесь присоединиться к ReportID, то нет, вы не можете избежать большого количества строк. Когда вы опускаете таблицу «Отчет» и просто присоединяете «Пожертвование» к «Предоставить» в ReportId, вы по-прежнему получаете 24 строки.

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

Но суть в том, что в реальном мире не имеет смысла сопоставлять пожертвования и гранты . Это совершенно независимые вещи, которые по сути не имеют ничего общего друг с другом.

В базе данных оператор, приведенный выше, объединит каждую строку в Грантах с каждой соответствующей строкой в ​​Пожертвовании. Получившиеся 24 строки действительно не должны вас удивлять.

Когда вам нужно представить независимые вещи пользователю, вы должны использовать средство составления отчетов или веб-приложение (например), которое выбирает независимые вещи, ну, независимо. Выберите пожертвования и поместите их в один раздел отчета или веб-страницы, затем выберите гранты и поместите их в другой раздел отчета или веб-страницы и т. Д.

Если таблица «Отчет» должна помочь вам записать, какие разделы входят в конкретный отчет, то вам нужна структура, похожая на эту:

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)
);
0 голосов
/ 07 марта 2011

Таблицы пожертвований и грантов выглядят практически одинаково.Вы можете сделать их одной таблицей и добавить столбец, похожий на DonationType.Снизил бы сложность на 1 таблицу.Теперь, если пожертвования и гранты совершенно разные и с ними связаны разные подтаблицы, то было бы идеальным держать их отдельно и объединять только по одному за раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...