Головоломка T / SQL - Как объединиться, чтобы создать отношение один к одному для двух не связанных между собой таблиц - PullRequest
1 голос
/ 08 мая 2009

Давайте предположим, что у меня есть две таблицы ... Foo и Bar. Они содержат следующие данные.

Table Foo:
Foo_Id
------
100
101

Table Bar:
Bar_Id
------
200
201

Как видите, в каждой таблице есть две записи. Я хотел бы объединить эти таблицы таким образом, чтобы они возвращали две записи; конечная цель - создать отношения «один к одному» для этих записей, даже если в этом состоянии они не имеют этих отношений. Результаты этих данных будут помещены в таблицу Foo_Bar для хранения этих новых отношений.

В идеале вывод должен выглядеть примерно так:

Foo_Id  Bar_Id
------  ------
100     200
101     201

Этот код будет использоваться в хранимой процедуре T / SQL. Я мог бы легко написать это с помощью цикла while, но я бы предпочел не использовать цикл while, потому что в реальном приложении будет гораздо больше данных, чем четыре записи, и будет вызываться несколькими пользователями много раз в день.

Заранее спасибо!

EDIT:

Это более или менее проблема инвентаря ... У меня есть 100 кусочков пиццы и 100 человек, которые говорят, что хотят кусочек пиццы. Таблица Foo_Bar - это способ назначить один кусок пиццы на человека. Таблица существует, и это решение загрузит данные для таблицы.

Ответы [ 5 ]

5 голосов
/ 08 мая 2009

попробуйте это:

declare @Foo table (Foo_Id int)
INSERT INTO @Foo VALUES (100)
INSERT INTO @Foo VALUES (101)
declare @Bar table (Bar_Id int)
INSERT INTO @Bar VALUES (200)
INSERT INTO @Bar VALUES (201)


SELECT
    dt_f.Foo_Id
        ,dt_f.RowNumber
        ,dt_b.Bar_Id
    FROM (SELECT
              Foo_Id, ROW_NUMBER() OVER(ORDER BY Foo_Id) AS RowNumber
              FROM @Foo
          ) dt_f
        INNER JOIN (SELECT
                        Bar_Id, ROW_NUMBER() OVER(ORDER BY Bar_Id) AS RowNumber
                        FROM @Bar
                   ) dt_b ON dt_f.RowNumber=dt_b.RowNumber
2 голосов
/ 08 мая 2009

Назначение инвентаря обычно выполняется по одной строке за раз. Использование наборов для этого прекрасно, но это своего рода парадигма «пакетной обработки». Я предполагаю, что разные люди встают в очередь и покупают пиццу со стола инвентаря. Mssql имеет несколько полезных советов для этого шаблона get-next-available-item - посмотрите на подсказку READPAST. Чтобы приобрести пиццу, вы можете сделать что-то вроде

UPDATE mytable WITH (READPAST) SET AcquiringUserID = @userId where AcquiringUserId is null
2 голосов
/ 08 мая 2009

Из приведенного вами примера вы можете использовать тот факт, что bar_id = 100 + foo_id

select foo.foo_id, bar.bar_id
from foo inner join bar on foo.foo_id +100 = bar.bar_id

.. но, может быть, это просто упрощение в вашем примере?

Если между идентификаторами нет взаимосвязи, тогда это не совсем реляционные данные , и нет простого способа объединить строки в реляционной базе данных.

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

2 голосов
/ 08 мая 2009

выберите foo_id, bar_id из внутреннего бара соединения foo на foo_id = (bar_id -100)

0 голосов
/ 08 мая 2009

выберите из каждой таблицы как вложенный оператор выбора с помощью функции ранга, затем присоединитесь к рангу.

select foo_id, bar_id
from (select foo_id, rank() over (partition by foo_id order by foo_id) as [Rank] from foo) f
left join (select bar_id, rank() over (partition by bar_id order by bar_id) as [Rank] from bar) b
on f.Rank = b.Rank
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...