2015-11-23 3 views
1

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

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

RouteId ShopId 
------------------------------------ 
1   111 
1   222 
2   111 
2   222 
2   333 
3   111 
3   222 
3   333 
3   444 

OrderId  ShopId 
------------------------------------ 
11   111 
11   222 
11   333 
12   111 
12   222 
13   111 
13   333 

Я хочу, чтобы результирующий набор как этот

OrderId  ShopId RouteId 
------------------------------------ 
11   111  2 
11   222  2 
11   333  2 
12   111  1 
12   222  1 
13   111  NULL 
13   333  NULL 

У меня есть около 50k-100k заказов, так что я не хочу использовать курсоры или если нет необходимости какой-либо другой цикл.

Любая помощь очень ценится.

Зоран

+0

Вот отличное место для начала. http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/ –

+1

Я не получаю ничтожных голосов. Для меня это конкретный вопрос. – Paparazzi

ответ

0

Использование LEFT JOIN положить NULL полей вспомогательной таблицы (RouteTable) там нет corrispondence в РЕГИСТРИРУЙТЕСЬ положение.

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

SELECT O.*, R.RouteId 
FROM OrderTable O 
LEFT OUTER JOIN RouteTable R 
ON O.ShopId = R.ShopId 
+0

Пожалуйста, добавьте некоторое описание, почему это решит проблему. –

0

Мне нравится XML ответ от Георгоса лучше, но я начал на этом

select t1.* 
from 
(
select cteS.OrderID, cteR.RouteID, count(*) as count 
    from cteS 
    join cteR 
     on cteS.StoreID = cteR.StoreID 
group by cteS.OrderID, cteR.RouteID 
) t1 
join 
(
select cteS.OrderID, count(*) as count 
    from cteS 
group by cteS.OrderID 
) t2 
on t1.OrderID = t2.OrderID 
and t2.count = t2.count 

или

select OrderID, RouteID 
    from store 
    join route 
     on store.storeID = route.storeID 
except 
select OrderID, RouteID 
    from store 
    full outer join route 
     on store.storeID = route.storeID 
where store.storeID is null or route.storeID is null 
1

Вы можете использовать FOR XML PATH для того, чтобы введите в строку стоимость всех магазинов за OrderId и за RouteId:

;WITH RoutesCTE AS (
    SELECT RouteId, 
     (SELECT ShopId 
     FROM routes AS r2 
     WHERE r2.RouteId = r1.RouteId 
     ORDER BY ShopId 
     FOR XML PATH('')) AS RouteShops 
    FROM routes AS r1 
    GROUP BY RouteId 
), OrdersCTE AS (
    SELECT OrderId, ShopId, 
     (SELECT ShopId 
     FROM orders AS o2 
     WHERE o2.OrderId = o1.OrderId 
     ORDER BY ShopId 
     FOR XML PATH('')) AS OrderShops 
    FROM orders AS o1 
) 
SELECT OrderId, ShopId, c2.RouteId 
FROM OrdersCTE AS c1 
LEFT JOIN RoutesCTE AS c2 ON c1.OrderShops = c2.RouteShops 

В приведенных выше КТР RouteShops и OrderShops держать значение XML всех магазинов в RouteId и OrderId соответственно.

Так, например, RoutesCTE возвращает следующие результаты:

RouteId RouteShops 
----------------------------------------------------------------- 
1  <ShopId>111</ShopId><ShopId>222</ShopId> 
2  <ShopId>111</ShopId><ShopId>222</ShopId><ShopId>333</ShopId> 
3  <ShopId>111</ShopId><ShopId>222</ShopId><ShopId>333</ShopId><ShopId>444</ShopId> 

Сравнивая эти два поля мы можем найти точные совпадения (если таковые имеются).

Demo here

Примечание: Этот запрос может возвращать более одного маршрута за OrderId если routes таблица содержит RouteId S, имеющие ту же самую комбинацию ShopId с. В этом случае вы должны играть с RoutesCTE (включая, например, ROW_NUMBER).

+0

Теперь это пятно – Paparazzi

Смежные вопросы