SQL, отображающийся между несколькими таблицами

Это - вопрос о дизайне SQL. Во-первых, установка. У меня есть три таблицы:

  1. A, который автоматически заполняется на основе запроса против связанного сервера. Данные в этой таблице не могут быть изменены;
  2. B, который имеет всего приблизительно дюжину строк, содержа названия наборов Как;
  3. AtoB, который является таблицей отображения который, Как организованы в именованные наборы, с внешними ключами на обоих столбцах;

SQL Mapping Table

Например, A содержит:

  1. Жираф
  2. Сова
  3. Тигр

И B содержит:

  1. Сиэтлский зоопарк
  2. Зоопарк Сан-Хосе

И AtoB содержит:

1,1 (Жираф в Сиэтле)
2,1 (Сова в Сиэтле)
3,1 (Тигр в Сиэтле)
2,2 (Сова в Сан-Хосе)

Теперь, проблема:

Меня попросили включать в некоторые из этих объектов наборов, не найденных в A. Так, я составляю таблицу, C, с теми же идентификационными данными и столбцами Name как A, и заполняю их. В соответствии с более ранним примером, скажем, C содержит:

  1. Дракон

Вопрос, как я включаю объекты от C в AtoB? Что, если я должен включать Дракона в Сиэтлский Зоопарк?

Мой первый инстинкт, будучи наивным, должен был создать представление V содержащий объединение A и C, и изменяющий AtoB, чтобы быть VtoB. Это то, где моя заплатившая наивность: нельзя создать внешний ключ к представлению.

Я подозреваю, что существует стандарт, корректные средства связи одного или нескольких A ИЛИ C с B.

6
задан xiº 3 July 2017 в 14:38
поделиться

4 ответа

Чтобы расширить решение Артура Томаса, вот профсоюз без того, где в подселении, чтобы вы могли создать универсальный вид:

SELECT A.Name as Animal, B.Name as Zoo FROM A, AtoB, B
    WHERE AtoB.A_ID = A.ID && B.ID = AtoB.B_ID 
UNION
SELECT C.Name as Animal, B.Name as Zoo FROM C, CtoB, B
    WHERE CtoB.C_ID = C.ID && B.ID = CtoB.B_ID

, вы можете выполнить вроде запроса:

SELECT Animal FROM zoo_animals WHERE Zoo="Seattle Zoo"
10
ответ дан 8 December 2019 в 14:43
поделиться

Что вы хотите сделать, так это поместить Дракона в A, и если вы хотите выбрать ВСЕ записи из A, независимо от того, есть ли у них соответствующая запись в AtoB, сделайте ВЛЕВОЕ ВРЕМЕННОЕ СОВМЕСТНОЕ ПОЛОЖЕНИЕ. Что-то вроде этого:

SELECT * FROM A
LEFT OUTER JOIN AtoB
ON A.id = AtoB.A_ID

Правка: Это сработает только в том случае, если вы сможете добавлять свои новые записи в A. Я пропустил тот факт, что вы не можете этого сделать. Я думаю, что решение Артура Томаса - это то, чего вы хотите.

0
ответ дан 8 December 2019 в 14:43
поделиться

Чем работает мозг, тем лучше, если с ним что-то много делать. Некоторые утверждают, что «это как мышца,» но это упрощает слишком далеко.

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

Однажды я провел вечер запоминания первых 100 цифр pi.

Так что же?

Эйнштейн цитируется как никогда не запоминающий никаких телефонных номеров. Он сказал: «Это то, для чего у меня есть телефонная книга.»

Та же сделка здесь. Если вы хотите впечатлить себя и, возможно, своих друзей, конечно, почему нет. Но это умственное упражнение, а не действительно полезный навык.


При кодировании, если вы не работаете преимущественно с ассемблером, вы будете использовать шестнадцатеричные числа только редко. Имеет смысл использовать шестнадцатеричные числа в контекстах, где эти числа будут битово сдвинуты. Например, можно замаскировать байт с помощью команды AND-ing по отношению к 0xFF. Числа, связанные с побитовым сдвигом, знаковыми битами ИЛИ и XOR, также могут иметь большой смысл как шестнадцатеричные. Числа, используемые для ежедневной арифметики, обычно лучше всего выражать десятичными числами.

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

-121--3498633-

Я предпочитаю следующее решение (требуется Джанго > = 1,0).

settings.py

INSTALLED_APPS+= ('django.contrib.flatpages',)

urls.py

urlpatterns+= patterns('django.contrib.flatpages.views',
    url(r'^about-us/$', 'flatpage', {'url': '/about-us/'}, name='about'),
    url(r'^license/$', 'flatpage', {'url': '/license/'}, name='license'),
)

В шаблонах

[...]
<a href="{% url about %}"><span>{% trans "About us" %}</span></a>
<a href="{% url license %}"><span>{% trans "Licensing" %}</span></a>
[...]

или в коде

from django.core.urlresolvers import reverse
[...]
reverse('license')
[...]

Это путь вам не нужно использовать django.contrib.flatpages.middleware.FlatpageFallbackMiddleware , и реверс работает как обычно, не записывая столько кода, сколько в других решениях.

Ура.

-121--2178529-

Артур Томас имеет хорошее решение, другим возможным решением является добавление столбца в таблицу связей, указывающего, с какой таблицей (A или C) она связана. Затем примените отношения с помощью триггеров, а не внешних ключей. Но на самом деле решение Артура является предпочтительным способом такого рода действий.

1
ответ дан 8 December 2019 в 14:43
поделиться

, Если вы не можете вставить Дракона затем, необходимо будет составить другую таблицу и другую таблицу ссылки. Проблема создает уникальный набор данных, которые должны храниться (другая таблица), который не может быть тем же набором как A. Так как это не тот же набор затем, вы больше не можете использовать таблицу ссылки (AtoB), который имеет внешние ключи, которые гарантируют, что ссылка является ссылкой от набора A. Таким образом, вы могли составить таблицы как это:

идентификационное
  • imaginary_creatures
    • название

    imaginary_creatures_to_b

    • imaginary_creatures_id (ссылаются на imaginary_creatures таблицу)
    • b_id (ссылаются на таблицу зоопарков)

    Позже, когда вы хотите получить все создания в зоопарке, можно сделать ОБЪЕДИНЕНИЕ

    SELECT A.Name FROM A where A.ID IN 
       (SELECT AB.A_ID FROM AtoB AB WHERE B_ID = 
          (SELECT B.ID FROM B WHERE B.Name = 'Zoo Name'))
    UNION
    SELECT i.name FROM imaginary_creatures i i.id IN 
       (SELECT ic.imaginary_creatures_id FROM imaginary_creatures_to_c ic 
        WHERE ic.b_id = (SELECT B.ID FROM B WHERE B.Name = 'Zoo Name'))
    

    может быть лучший способ записать это, но это должно работать на цели.

    5
    ответ дан 8 December 2019 в 14:43
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: