2014-12-29 2 views
-1

Я пытаюсь сократить цикл на SQL Server, и я немного тупик. Мне нужно объединить покупки и продажи по заданным критериям. Для этих критериев группа покупок может соответствовать группе продаж. Не каждая покупка может соответствовать каждой продаже (и наоборот), но одна покупка может сравниться с более чем одной продажей (и наоборот). Я могу легко получить временную таблицу всех возможных совпадений, но сложная часть соединяет одну покупку с одной продажей только с использованием только один раз.Избегание циклов в совпадающих записях

Хотя цикл в какой-то мере кажется неизбежным, я бы предпочел не использовать курсор из-за объема записей. Я хотел бы выбрать один набор критериев за один раз (например, захватить первую пару для каждого элемента). Я пытаюсь использовать временную таблицу #T возможных совпадений, сужать их до пар и повторять. По крайней мере, я пишу 100 раз вместо миллиона.

Вот фрагмент таблицы температуры #T:

MatchID BuyID SellID 
     1  91  59 
     2  91  60 
     3  97  59 
     4  97  60 

Для выше, я могу держать либо MatchIDs 1 и 4 или 2 и 3. Я пытался использовать этот алгоритм, чтобы сузить:

  1. Удалить запись с большей MatchID но такой же BuyID
  2. Удалить запись с большей MatchID но такой же SellID

Если я это сделаю, шаг (1) удаляет записи 2 и 4, а шаг (2) удаляет запись 3. Я могу изменить порядок записей в SQL, так что пары имеют разные идентификаторы MatchID, но я связан тем, что я может работать в SQL Server. Я попытался упорядочить матчи по-разному, но ничто не дает мне что-то, к чему я могу применить алгоритм.

У кого-нибудь еще была такая проблема?

+0

Что должно быть сопоставлено в этом случае: (1,2,3), (2,2,4), (3,3,5)? –

+0

Является ли это столь же сложным, как данные действительно получают? Или возможно, что существует 5 'BuyID' строк для BuyID = 98 и только 3' BuyID' для BuyID = 99? Вы говорите, что они не будут соответствовать друг другу, так может ли быть так, что 'BuyID' из 98 также соответствует только значениям SellID' 59 и 60? В этом случае 59 и 60 уже использовались для значений BuyID 91 и 97, так что делать? –

+0

Данные действительно усложняются, но я не хотел, чтобы этот вопрос был слишком запутанным. Считайте, что BuyID 91 можно сопоставить с SellID 59 или 60, и то же самое для BuyID 97. Однако я могу только соответствовать одному BuyID за раз, поэтому мне нужно выбрасывать совпадения, которые являются дубликатами, не делая слишком много проходит в петле. –

ответ

0

Жесткий! Я думаю, что это работает.

CREATE TABLE #t (MatchID INT, BuyID INT, SellID INT) 
INSERT #t 
SELECT 1, 91, 59 UNION ALL 
SELECT 2, 91, 60 UNION ALL 
SELECT 3, 97, 59 UNION ALL 
SELECT 4, 97, 60 


DELETE 
    #t 
WHERE 
    MatchID IN 
(
    SELECT DISTINCT 
    t1.MatchID 
    FROM 
    (
    SELECT 
     MatchID, 
     ROW_NUMBER() OVER (PARTITION BY SellID ORDER BY SellID) AS Row 
    FROM 
     #t 
    ) AS t1 
    CROSS JOIN 
    (
     SELECT 
     MatchID, 
     ROW_NUMBER() OVER (PARTITION BY BuyID ORDER BY BuyID) AS Row 
     FROM 
     #t 
    ) AS t2 
    WHERE 
    t1.Row <> 1 AND 
    t2.Row <> 1 
) 

SELECT * FROM #t 
+0

Вот и все! Благодаря! –

0

Используйте window Function, чтобы найти greater MatchID для SellId и BuyID. Затем используйте CTE для удаления записей

CREATE TABLE #test 
    (
    MatchID INT, 
    BuyID INT, 
    SellID INT 
) 

INSERT #test 
VALUES (1,91,59), 
     (2,91,60), 
     (3,97,59), 
     (4,97,60); 

WITH cte 
    AS (SELECT Row_number()OVER(partition BY buyid ORDER BY matchid DESC)B_rn, 
       Row_number()OVER(partition BY sellid ORDER BY matchid DESC)S_rn, 
       * 
     FROM #test) 
DELETE FROM cte 
WHERE 1 IN (b_rn, s_rn) 
Смежные вопросы