2010-09-08 5 views
1

У меня есть данные в следующем формате.Создание иерархии в SQL Server

Таблица 1

e_id e_name e_type 
------------------------- 
1  CBC  2 
2  ABC  3 
3  N2  1 
4  CBC1 3 
5  ABC1 3 
6  N1  1 

Таблица 2

N_ID N_Name 
--------------- 
3  N2 
6  N1 

Таблица 3

N_ID E_ID 
------------ 
3  1 
3  2 
3  3 
6  4 
6  5 
6  6 

И я хочу, чтобы построить иерархию следующим образом.

e_id e_name  e_type n_id 
------------------------------------ 
6  N1   1  6 
4  - ABC1  3  6 
5  - CBC1  3  6 
3  N2   1  3 
4  - ABC  3  3 
5  - CBC  2  3 

С заказом по узлам (по возрастанию), дочерние узлы (по возрастанию).

Я пытался сделать что-то похожее на это,

SELECT u.e_id, 
CASE WHEN e_TYPE_ID = 1 THEN u.e_name ELSE ' - ' + u.e_name END e_name, 
e_TYPE_ID, su.n_ID 
FROM table1 u 
INNER JOIN table3 su on u.e_id = su.e_id 
WHERE EXISTS (SELECT N_ID FROM table2 WHERE N_ID = CASE WHEN u.e_TYPE_ID = 1 THEN u.e_id ELSE n_ID END) 
ORDER BY e_TYPE_ID, u.e_name,n_id 

Но я не в состоянии получить правильный порядок, есть лучший способ сделать это?

+0

Иерархия всегда два уровня (то есть родитель-потомок, никогда Grandparent-родитель-ребенок)? –

+0

Я тебя не понял? мой также два уровня (N1 -parent, ABC, CBC-ребенок) –

+0

Тогда вам не нужно CTE. :) Вам нужно убить этого администратора из другого отдела. –

ответ

1

Если вы используете SQL Server 2008 (или 2008 R2), я бы предложил использовать Иерархические идентификаторы, как показано в Model Your Data Hierarchies With SQL Server 2008.

+1

Я думаю, что это лишний случай в этом конкретном случае. –

+0

В общем, трудно понять, что-то «переполнено» или нет, пока вы не узнаете о шаблонах использования, характеристиках производительности и т. Д. Существует много историй успеха, использующих концепцию идентификатора иерархии. ИМХО, даже если дело просто, если это правильный способ (tm) что-то сделать, это почти всегда, как это должно быть сделано. Я поддерживаю свое первоначальное предложение. –

+0

Хорошая статья - очень интересно. – Sam

0

обращу вы на правильном пути, вы будете нуждаться в КТРЕ (общее выражение таблицы) для выполнения этой задачи:

;with EH as 
(
select 1 level, * from Table1 t1 where e_type = 1 
union all 
select level+1, * from EH 
join Table3 t3 on eh.e_id = t3.e_id 
join Table3 t32 on t3.n_id = t32.n_id and t3.e_id 

--FUUUUUUUUUUUUUUUUUUUUU!!!!!!!!!!!!!!1111 

[Update]

Зачем вам нужен этот спагетти таблицы в любом случае? Почему бы вам не оставить все в одном или двух таблицах?

+0

Я знаю, что мне тоже не нравится, как он разработан, мы используем таблицы из другой базы данных отдела. –

2

Использование:

WITH summary AS (
    SELECT a.e_id, 
     a.e_name, 
     a.e_type, 
     b.n_id, 
     CASE WHEN e_type = 1 THEN e_type ELSE 2 END AS rank 
    FROM TABLE1 a 
    JOIN TABLE3 b ON b.e_id = a.e_id) 
    SELECT s.e_id, 
      CASE 
      WHEN s.rank > 1 THEN ' - '+ s.e_name 
      ELSE s.e_name 
      END AS e_name, 
      s.e_type, 
      s.n_id 
    FROM summary s 
ORDER BY s.n_id DESC, s.rank, s.e_name 

я тестировал с помощью:

WITH table2 AS (
    SELECT 3 AS n_id, 'N2' AS n_name 
    UNION ALL 
    SELECT 6, 'N1'), 
    table1 AS (
    SELECT 1 AS e_id, 'CBC' AS e_name, 2 AS e_type 
    UNION ALL 
    SELECT 2, 'ABC', 3 
    UNION ALL 
    SELECT 3, 'N2', 1 
    UNION ALL 
    SELECT 4, 'CBC1', 3 
    UNION ALL 
    SELECT 5, 'ABC1', 3 
    UNION ALL 
    SELECT 6, 'N1', 1), 
    table3 AS (
    SELECT 3 AS n_id, 1 AS e_id 
    UNION ALL 
    SELECT 3, 2 
    UNION ALL 
    SELECT 3, 3 
    UNION ALL 
    SELECT 6, 4 
    UNION ALL 
    SELECT 6, 5 
    UNION ALL 
    SELECT 6, 6), 
    summary AS (
    SELECT a.e_id, 
      a.e_name, 
      a.e_type, 
      b.n_id, 
      CASE WHEN e_type = 1 THEN e_type ELSE 2 END AS rank 
    FROM TABLE1 a 
    JOIN TABLE3 b ON b.e_id = a.e_id) 
    SELECT s.e_id, 
     CASE 
      WHEN s.rank > 1 THEN ' - '+ s.e_name 
      ELSE s.e_name 
     END AS e_name, 
     s.e_type, 
     s.n_id 
    FROM summary s 
ORDER BY s.n_id DESC, s.rank, s.e_name 
+0

@ Joe Stefanelli: новый и улучшенный. –

+0

Я грубый грейдер, поэтому я все равно отдаю только часть кредитов. :-) Только по совпадению ваш «ORDER BY s.n_id DESC ...» получает N1 перед N2. Обмен N1 и N2 в таблице 1, так что N1 - e_id 3, а N2 - e_id 6, а N2 будет сортироваться до N1. –

+0

@ Джо Стефанелли: Я требую пересчета? =) –

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