Объединение таблиц с анонимными внешними ключами - PullRequest
0 голосов
/ 18 апреля 2011

Относящиеся

В связи с другим моим вопросом:

Комментарий системы проектирования

Дизайн данных

Допустим, у меня есть таблица тегов:

tblTags
-------------
TagID (int)
Name (string)

И две таблицы содержания:

tblBlogs
-------------
Anchor (GUID, Primary Key)
BlogTitle (string)
+ More custom fields

tblTutorials
-------------
Anchor (GUID, Primary Key)
TutorialTitle (string)
+ More custom fields

Также будет больше столов с якорями, а не только 2.

Затем, чтобы связать тег с вышеуказанным объектом:

tblTagAnchors
-------------
TagID (int, Foreign Key)
Anchor (GUID, Foreign Key)

Мой вопрос заключается в том, что после того, как я собрал свои ассоциации блогов и учебных пособий с определенным тегом, есть ли способ написать запрос для возврата блогов или учебных пособий с определенным тегом? Не нужно иметь отдельные запросы для блогов и учебников?

Основное использование будет для поиска, что-то вроде (псевдо):

select from tblBlogs and tblTutorials where the GUID exists in tblTagAnchors where tagID = 5

for each record returned
    if record from Blog
        response.write("<a href=blogView.aspx?ID=" + recID)
    else if record from Tutorial
        response.write("<a href=tutorialView.aspx?ID=" + recID)
next

Я использую SQL Server 2008 Express и ASP.net 4 (c #), если это имеет большое значение с Linq для SQL, но все, что мне нужно, - это ответ на основе дизайна, а не какой-либо код, за исключением случаев, когда для демонстрации.

Это единственный способ сделать это с несколькими запросами?

Ответы [ 3 ]

5 голосов
/ 18 апреля 2011

Это был бы "обычный" подход.

enter image description here

select
      p.PublicationID 
    , p.PublicationType 
    , p.PublicationTitle
    , t.TagID
    -- other blog/tutorial specific fields here
from Publication    as p
left join Blog      as b on (b.PublicationID = p.PublicationID and p.PublicationType = 'B')
left join Tutorial  as t on (t.PublicationID = p.PublicationID and p.PublicationType = 'T')
join PublicationTag as x on x.PublicationID = p.PublicationID
join Tag            as t on t.TagID = x.TagID ;

Вы можете упаковать это в представление, чтобы помочь изолировать любые будущие изменения схемы от кода приложения.

3 голосов
/ 18 апреля 2011

Я бы порекомендовал использовать профсоюз.Этот запрос будет иметь только один набор результатов, но под капотом он объединяется с запросами вместе.

Select b.rec_id,'Blog' as type from tblBlogs b
inner join tblTagAnchors ta on ta.anchor = b.anchor
where ta.tagid = 5
union
Select t.rec_id,'Tutorials' as type from tblTutorials t
inner join tblTagAnchors ta on ta.anchor = t.anchor
where ta.tagid = 5

Тогда в вашем коде vb просто сделайте if в поле типа.В linq вам нужно написать запрос с помощью команды .union.Я только что написал общее решение SQL.Хотя его легко можно преобразовать в linq.

Поскольку условные внешние ключи заставляют меня хотеть затвора.В современном дизайне базы данных вы всегда должны избегать ключа, который может идти к нескольким таблицам, трудно применить CRUD и сделать запрос более запутанным.Я бы предложил создать супер-тип tblBlogs и tblTutorials, такие как tblWebsites и заставить ключ перейти к супертипу.

1 голос
/ 18 апреля 2011

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

По сути, ваш запрос будет СОЮЗОМ из двух подзапросов, но я бы сделал это несколько иначе, чем предлагал @JStead, что-то вроде этого:

SELECT
  OutputString = '<a href=' + SrcName + 'View.aspx?ID=' + CAST(x.recID AS varchar)
FROM (
  SELECT 'blog' AS SrcName, Anchor, recID
  FROM tblBlogs
  UNION ALL
  SELECT 'tutorial' AS SrcName, Anchor, recID
  FROM tblTutorials
) x
  INNER JOIN tblTagAnchors ta ON x.Anchor = ta.Anchor

Как видите, запрос возвращает данные, готовые для вывода. Поэтому логика вашего клиента упрощается до чего-то вроде этого:

for each record returned
    response.write(OutputString)
next
...