2016-02-28 3 views
1

Мне нужно подсчитать края между соседями узлов в графе в SQL Server, тогда как у меня есть таблицы как GraphNodes и GraphEdges. Структура таблиц доступна в previous questionПередача параметров на запрос в SQL Server

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

  1. взять узел говорят V от GraphNodes

  2. должны иметь список DISTINCT соседей для V (например, в TABLE переменная SQL)

  3. чека (COUNT DISTINCT) связь между соседями V в GraphEdges
  4. выхода В с отчетливыми связями между соседями

запросом у меня для одного узла работает нормально, т.е.

SELECT GN.id, COUNT(DISTINCT(CONCAT(GE.Source_Node,'-', GE.Target_Node))) AS NeighborLinks 
FROM GraphEdges GE 
JOIN GraphNodes GN ON GN.id = 512 
WHERE Source_Node IN (SELECT DISTINCT Target_Node FROM GraphEdges WHERE Source_Node = 512 
         UNION ALL 
         SELECT DISTINCT Source_Node FROM GraphEdges WHERE Target_Node = 512 
        ) 
    AND Target_Node IN (SELECT DISTINCT Target_Node FROM GraphEdges WHERE Source_Node = 512 
         UNION ALL 
         SELECT DISTINCT Source_Node FROM GraphEdges WHERE Target_Node = 512 
        ) 
GROUP BY GN.id 

Я взял id = 512 в качестве образца, где находится id в GraphNodes. Этот запрос выводит как:

+-------+-----------------+ 
| id | NeighborLinks | 
+-------+-----------------+ 
| 512 | 6    | 
+-------+-----------------+ 

Причина использования UNION ALL в пункте WHERE является то, что id т.е. 512 существует в обеих колонках т.е. Source_Node и Target_Node, а также, так что должны выбрать DISTINCT соседи из обеих колонок необходимо. Более того, используя тот же список для GE.Source_Node и GE.Target_Node, потому что нужно проверять ссылки только между соседями V т. Е. 512.
Вопрос заключается в том, как использовать то, что я думаю, что переменная TABLE или любой другой способ, чтобы разобраться в этой проблеме предоставления длинного списка значений вместо 512

Я пришел к этому решению в отношении переменной таблицы, но получил сообщение об ошибке с помощью табличные переменные внутри запроса как:
Try 1

DECLARE @ID TABLE(id INT) 
DECLARE @S_Neighbor TABLE (id INT) 
DECLARE @T_Neighbor TABLE (id INT) 

INSERT INTO @ID SELECT id FROM GraphNodes 

INSERT INTO @S_Neighbor SELECT DISTINCT Source_Node 
         FROM GraphEdges 
         WHERE Target_Node IN (SELECT id FROM @ID) 
--UNION ALL 
INSERT INTO @T_Neighbor SELECT DISTINCT Target_Node 
         FROM GraphEdges 
         WHERE Source_Node IN (SELECT id FROM @ID) 

SELECT GN.id,COUNT(DISTINCT(CONCAT(GE.Source_Node,'-', GE.Target_Node))) AS Mutual_Links 
FROM GraphEdges GE 
JOIN GraphNodes GN ON GN.id = @ID 
WHERE Source_Node IN (SELECT DISTINCT Target_Node 
         FROM GraphEdges 
         WHERE Source_Node IN @T_Neighbor 

         UNION ALL 

         SELECT DISTINCT Source_Node 
         FROM GraphEdges 
         WHERE Target_Node IN @S_Neighbor) 
    AND Target_Node IN (SELECT DISTINCT Target_Node 
         FROM GraphEdges 
         WHERE Source_Node IN @S_Neighbor 

         UNION ALL 

         SELECT DISTINCT Source_Node 
         FROM GraphEdges 
         WHERE Target_Node IN @T_Neighbor) 
GROUP BY GN.id 

Я также попытался это:
Попробуйте 2

DECLARE @ID_COUNTER INT 
DECLARE @MAX_ID INT 

SET @ID_COUNTER = 1 
SET @MAX_ID = 148410 

WHILE @ID_COUNTER <= @MAX_ID 
BEGIN 
    (
    SELECT GN.id, 
    COUNT(DISTINCT(CONCAT(GE.Source_Node,'-', GE.Target_Node))) AS Mutual_Links 
    FROM GraphEdges GE 
    JOIN GraphNodes GN ON GN.id = @ID_COUNTER 
    WHERE Source_Node IN (SELECT DISTINCT Target_Node 
          FROM GraphEdges WHERE Source_Node = @ID_COUNTER 
          UNION ALL 
          SELECT DISTINCT Source_Node 
          FROM GraphEdges WHERE Target_Node = @ID_COUNTER 
         ) 
     AND Target_Node IN (SELECT DISTINCT Target_Node 
          FROM GraphEdges WHERE Source_Node = @ID_COUNTER 
          UNION ALL 
          SELECT DISTINCT Source_Node 
          FROM GraphEdges WHERE Target_Node = @ID_COUNTER 
         ) 
    GROUP BY GN.id 
    ) 
    SET @ID_COUNTER += 1 
END 

Я использовал @MAX_ID = 3, и для возврата результата потребовалось 56 секунд, тогда как @MAX_ID изначально = 148410.Хотя возвращаемые значения NeighborLinks правильны, но результат, показанный в трех отдельных окнах для как:

id NeighborLinks 
1 53 

id NeighborLinks 
2 318 

id NeighborLinks 
3 297 

+0

... Вы написали все это, чтобы спросить, как передать список значений int в качестве параметра? –

+1

Вы уже предлагаете переменную таблицы самостоятельно. Что удерживает вас от использования переменных таблицы? Альтернативой будет использование временной таблицы для хранения идентификатора. –

+0

@IvanStarostin Не все да, но это проблема с двумя краями, одна из них заключается в том, как сохранять и передавать значения int в качестве параметра повторно, а другое - как присоединяться к одному столбцу дважды – maliks

ответ

1

Я думаю, что вы ищете что-то как фрагмент ниже.

Я создал временную таблицу для узлов графа (#graph_edges). Узлы, для которых вы хотите найти число (разных) соседей, находятся во временной таблице #nodes.

CREATE TABLE #graph_edges(source_node INT NOT NULL,target_node INT NOT NULL); 

CREATE TABLE #nodes(id INT NOT NULL PRIMARY KEY); 
--INSERT INTO #nodes(id)VALUES(512),(513),(514); -- specific nodes to look up in the graph 
INSERT INTO #nodes(id) 
SELECT source_node FROM #graph_edges UNION SELECT target_node FROM #graph_edges; -- lookup for all distinct nodes ID's in the graph 


SELECT id,neighbor_links=COUNT(*) 
FROM 
    (
     SELECT n.id,l=ge.source_node,r=ge.target_node 
     FROM #nodes AS n 
      INNER JOIN #graph_edges AS ge ON 
       ge.source_node=n.id 
     UNION -- union of the two sets, this filters duplicate rows (ie no duplicate source_node,target_node row will appear in the derived table) 
     SELECT n.id,l=ge.target_node,r=ge.source_node 
     FROM #nodes AS n 
      INNER JOIN #graph_edges AS ge ON 
       ge.target_node=n.id 
    ) AS l 
GROUP BY id 
ORDER BY id; 

DROP TABLE #nodes; 
DROP TABLE #graph_edges; 
+0

@TT .-- Я выполнил ваш ответ, но он возвращает строки '0', когда вы вставляете вручную значения VALUES INTO #nodes? – maliks

+0

@Taufel Вы заменили '# graph_nodes' вашей таблицей' GraphNodes' в скрипте? Результаты будут равны нулю, если на графике нет узлов. –

+0

@TT .-- Я думаю, что нет записи в скрипте как '# graph_nodes' – maliks

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