2010-07-30 1 views
4

У нас есть общая организационная структура таблицы, подумайте об иерархии дерева или пирамиды. У нас в основном есть несколько «деревьев», которые мы хотим показать. Для одной компании, одна для другой ETC.SQL Server Query или инструмент для отображения иерархических данных

Кто-нибудь знает о хорошем способе отображения этих данных? SQL Query было бы неплохо, сомневаюсь, что это будет возможно, но я бы не против использования какого-либо инструмента OTS (желательно свободного). Я также хотел бы избежать какого-либо отчета. Мне не нужно настоящее решение, просто нужно знать , если его возможно. Поэтому, если вы скажете SQL, если вы можете дать мне пример из 2 таблиц, показывающих корень, я останусь счастливым.

Структура довольно общий

alt text

И каждая таблица связана через суррогатный ключ CompanyID, CompanyGroupID и т.д.

Любые предложения о путях мы могли бы отобразить/запрос для этих данных? Последнее средство, чтобы написать быстрое приложение C# Windows ...

Мы хотели бы видеть его в виде дерева:

--      1-Company 
--     /  \ 
--    CompanyGroupA CompanyGroupB 
--   /  \    \ 
-- CompanyStoreA1 CompanyStoreA1 CompanyStoreB 
-- / \   / \ 
--Employee A   B  C 

В попытке угодить массы вот пример тестового скрипт для заполнения запроса ,

DECLARE @Company table (id int, name varchar(40)) 
INSERT @Company VALUES (1,'Living Things') 
INSERT @Company VALUES (2,'Boring Company') 


DECLARE @CompanyGroup table (id int, name varchar(40), CompanyID int) 
INSERT @CompanyGroup VALUES (1,'Pets',1) 
INSERT @CompanyGroup VALUES (2,'Humans',1) 
INSERT @CompanyGroup VALUES (3,'Electronics',2) 
INSERT @CompanyGroup VALUES (4,'Food',2) 


DECLARE @CompanyStore table (id int, name varchar(40), CompanyGroupID int) 
INSERT @CompanyStore VALUES (1,'PetsStoreA',1) 
INSERT @CompanyStore VALUES (2,'PetsStoreB',1) 
INSERT @CompanyStore VALUES (3,'PetsStoreC',1) 
INSERT @CompanyStore VALUES (4,'PetsStoreD', 1) 
INSERT @CompanyStore VALUES (5,'HumansStore',2) 
INSERT @CompanyStore VALUES (6,'FoodStore',3) 

Окончательное решение было довольно удивительным я изменил usp_DrawTree принять VARCHAR против Интс, потому что я должен был сделать мой запрос уникальные идентификаторы. Затем я просто сделал select/union all и построил родительские дочерние отношения.

select * into #TreeData from (
    select ID='C' + cast(id as varchar(10)), 
     ParentID=null, 
     DataForBox=name + '(' + cast(id as varchar(10)) + ')', 
     ExtraInfo='', 
     SortColumn=name 
    from Company c 
) 
union all (
    select ID='CG' + cast(id as varchar(10)), 
     ParentID=cg.CompanyID , 
     DataForBox=name + '(' + cast(id as varchar(10)) + ')', 
     ExtraInfo='', 
     SortColumn=name 
    from CompanyGroup cg join Company c on c.ID=cg.CompanyID 
) 
//union all rest of hierarchy 
) 
+0

Я думал, что это может быть легко просто запросить для каждого CompanyGroup для идентификатора, экспорт в CSV, а затем запросить все CompanyStores от экспорта компании Группы в CSV, а затем поместить их в закладки в Excel и создать отчет ... но даже это может быть грязно. – Nix

+0

сделал мой последний ответ на ваш вопрос? –

+0

Я имею в виду его квартиру. Я ищу визуальное дерево, как вы изображаете в своих комментариях для вставок. Сложно представить нижние уровни в дереве, когда вы смотрите на них в GridView. Мы будем смотреть на это Дерево и должны видеть разные ветви бок о бок. Я думаю, что это просто должно быть настраиваемое приложение или отчет. – Nix

ответ

0

Вы можете использовать службы отчетов, чтобы отобразить их обратно, которые вы получаете с помощью SQL 2008; если вам повезет, он может быть настроен уже, если не достаточно легко это сделать. Вы можете использовать функции детализации в службах отчетов, чтобы позволить пользователям легко и быстро выполнять бурение и удаление данных.

С точки зрения запроса; дерево растет или оно фиксируется? Однако SQL Query для получения данных из базы данных довольно прост.

Select 
    CompanyName, 
    CompanyGroupName, 
    CompanyStoreName, 
    CompanyEmployeeForename, 
    CompanyEmployeeSurname 

From tblCompanies com 
left outer join tblCompanyGroups cg 
on com.CompanyGroupID = cg.CompanyGroupID 

Left outer Join tblCompanyStore cs 
on com.CompanyID = cs.CompanyID 

left outer join tblCompanyEmployees ce 
on com.CompanyID = ce.CompanyName 
+0

Дерево закреплено до нижнего уровня. Но по большей части нижний уровень (сотрудники), вероятно, никогда не будет отображаться полностью. – Nix

1

вы не обеспечивают структуру таблицы, так вот пример рекурсивного CTE обработки дерева структуру:

--go through a nested table supervisor - user table and display the chain 
DECLARE @Contacts table (id varchar(6), first_name varchar(10), reports_to_id varchar(6)) 
INSERT @Contacts VALUES ('1','Jerome', NULL) -- tree is as follows: 
INSERT @Contacts VALUES ('2','Joe' ,'1')  --      1-Jerome 
INSERT @Contacts VALUES ('3','Paul' ,'2')  --     /  \ 
INSERT @Contacts VALUES ('4','Jack' ,'3')  --    2-Joe   9-Bill 
INSERT @Contacts VALUES ('5','Daniel','3')  --   /  \    \ 
INSERT @Contacts VALUES ('6','David' ,'2')  --  3-Paul   6-David  10-Sam 
INSERT @Contacts VALUES ('7','Ian' ,'6')  -- / \   / \ 
INSERT @Contacts VALUES ('8','Helen' ,'6')  -- 4-Jack 5-Daniel 7-Ian 8-Helen 
INSERT @Contacts VALUES ('9','Bill ' ,'1')  -- 
INSERT @Contacts VALUES ('10','Sam' ,'9')  -- 

DECLARE @Root_id char(4) 

--get complete tree--------------------------------------------------- 
SET @Root_id=null 
PRINT '@Root_id='+COALESCE(''''[email protected]_id+'''','null') 
;WITH StaffTree AS 
(
    SELECT 
     c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf 
     FROM @Contacts     c 
      LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id 
     WHERE [email protected]_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL) 
    UNION ALL 
     SELECT 
      s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1 
     FROM StaffTree   t 
      INNER JOIN @Contacts s ON t.id=s.reports_to_id 
    WHERE [email protected]_id OR @Root_id IS NULL OR t.LevelOf>1 
) 
SELECT * FROM StaffTree 


--get all below 2--------------------------------------------------- 
SET @Root_id=2 
PRINT '@Root_id='+COALESCE(''''[email protected]_id+'''','null') 
;WITH StaffTree AS 
(
    SELECT 
     c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf 
     FROM @Contacts     c 
      LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id 
     WHERE [email protected]_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL) 
    UNION ALL 
     SELECT 
      s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1 
     FROM StaffTree   t 
      INNER JOIN @Contacts s ON t.id=s.reports_to_id 
    WHERE [email protected]_id OR @Root_id IS NULL OR t.LevelOf>1 
) 
SELECT * FROM StaffTree 

--get all below 6--------------------------------------------------- 
SET @Root_id=6 
PRINT '@Root_id='+COALESCE(''''[email protected]_id+'''','null') 
;WITH StaffTree AS 
(
    SELECT 
     c.id, c.first_name, c.reports_to_id, c.reports_to_id as Manager_id, cc.first_name AS Manager_first_name, 1 AS LevelOf 
     FROM @Contacts     c 
      LEFT OUTER JOIN @Contacts cc ON c.reports_to_id=cc.id 
     WHERE [email protected]_id OR (@Root_id IS NULL AND c.reports_to_id IS NULL) 
    UNION ALL 
     SELECT 
      s.id, s.first_name, s.reports_to_id, t.id, t.first_name, t.LevelOf+1 
     FROM StaffTree   t 
      INNER JOIN @Contacts s ON t.id=s.reports_to_id 
    WHERE [email protected]_id OR @Root_id IS NULL OR t.LevelOf>1 
) 
SELECT * FROM StaffTree 

ВЫВОД:

@Root_id=null 
id  first_name reports_to_id Manager_id Manager_first_name LevelOf 
------ ---------- ------------- ---------- ------------------ ----------- 
1  Jerome  NULL   NULL  NULL    1 
2  Joe  1    1   Jerome    2 
9  Bill  1    1   Jerome    2 
10  Sam  9    9   Bill    3 
3  Paul  2    2   Joe    3 
6  David  2    2   Joe    3 
7  Ian  6    6   David    4 
8  Helen  6    6   David    4 
4  Jack  3    3   Paul    4 
5  Daniel  3    3   Paul    4 

(10 row(s) affected) 

@Root_id='2 ' 
id  first_name reports_to_id Manager_id Manager_first_name LevelOf 
------ ---------- ------------- ---------- ------------------ ----------- 
2  Joe  1    1   Jerome    1 
3  Paul  2    2   Joe    2 
6  David  2    2   Joe    2 
7  Ian  6    6   David    3 
8  Helen  6    6   David    3 
4  Jack  3    3   Paul    3 
5  Daniel  3    3   Paul    3 

(7 row(s) affected) 

@Root_id='6 ' 
id  first_name reports_to_id Manager_id Manager_first_name LevelOf 
------ ---------- ------------- ---------- ------------------ ----------- 
6  David  2    2   Joe    1 
7  Ian  6    6   David    2 
8  Helen  6    6   David    2 

(3 row(s) affected) 

EDIT основе на таблицах и данных ОП:

попробуйте что-нибудь li ке это:

SET NOCOUNT ON 
DECLARE @Company table (id int, name varchar(40)) 
INSERT @Company VALUES (1,'Living Things') 
INSERT @Company VALUES (2,'Boring Company') 

DECLARE @CompanyGroup table (id int, name varchar(40), CompanyID int) 
INSERT @CompanyGroup VALUES (1,'Pets'  ,1) 
INSERT @CompanyGroup VALUES (2,'Humans'  ,1) 
INSERT @CompanyGroup VALUES (3,'Electronics' ,2) 
INSERT @CompanyGroup VALUES (4,'Food'  ,2) 

DECLARE @CompanyStore table (id int, name varchar(40), CompanyGroupID int) 
INSERT @CompanyStore VALUES (1,'PetsStoreA' ,1) 
INSERT @CompanyStore VALUES (2,'PetsStoreB' ,1) 
INSERT @CompanyStore VALUES (3,'PetsStoreC' ,1) 
INSERT @CompanyStore VALUES (4,'PetsStoreD' ,1) 
INSERT @CompanyStore VALUES (5,'HumansStore' ,2) 
INSERT @CompanyStore VALUES (6,'FoodStore' ,3) 

--not provided by the OP, so I made it up 
DECLARE @CompanyEmployees table (id int, name varchar(10), reports_to_id int, CompanyStoreID int) 
INSERT @CompanyEmployees VALUES (1,'Jerome', NULL ,1) -- tree is as follows: 
INSERT @CompanyEmployees VALUES (2,'Joe' ,1  ,1)  --      PetsStoreA    PetsStoreB   PetStoreC   FoodStore 
INSERT @CompanyEmployees VALUES (3,'Paul' ,2  ,1)  --      1-Jerome     11-Alan   14-Ben    18-apple 
INSERT @CompanyEmployees VALUES (4,'Jack' ,3  ,1)  --     /  \    / \   /    / \ 
INSERT @CompanyEmployees VALUES (5,'Daniel',3  ,1)  --    2-Joe   9-Bill   12-Ally 13-Abby 15-Bill   19-pear 20-grape 
INSERT @CompanyEmployees VALUES (6,'David' ,2  ,1)  --   /  \    \       / \     /
INSERT @CompanyEmployees VALUES (7,'Ian' ,6  ,1)  --  3-Paul   6-David  10-Sam      16-Bjorn 17-Benny   21-rasin 
INSERT @CompanyEmployees VALUES (8,'Helen' ,6  ,1)  -- / \   / \ 
INSERT @CompanyEmployees VALUES (9,'Bill ' ,1  ,1)  -- 4-Jack 5-Daniel 7-Ian 8-Helen 
INSERT @CompanyEmployees VALUES (10,'Sam' ,9  ,1)  -- 
INSERT @CompanyEmployees VALUES (11,'Alan' ,NULL ,2)  --to see all trees, scroll--->> 
INSERT @CompanyEmployees VALUES (12,'Ally' ,11 ,2)  -- 
INSERT @CompanyEmployees VALUES (13,'Abby' ,11 ,2)  -- 
INSERT @CompanyEmployees VALUES (14,'Ben' ,NULL ,3)  --  
INSERT @CompanyEmployees VALUES (15,'Bill' ,14 ,3)  -- 
INSERT @CompanyEmployees VALUES (16,'Bjorn',15 ,3)  -- 
INSERT @CompanyEmployees VALUES (17,'Benny',15 ,3)  -- 
INSERT @CompanyEmployees VALUES (18,'apple',NULL ,6)  -- 
INSERT @CompanyEmployees VALUES (19,'pear' ,18 ,6)  -- 
INSERT @CompanyEmployees VALUES (20,'grape',18 ,6)  -- 
INSERT @CompanyEmployees VALUES (21,'rasin',21 ,6)  -- 
SET NOCOUNT OFF 

;WITH StaffTree AS 
(
    SELECT 
     c.id, c.name, c.reports_to_id, c.reports_to_id as Manager_id, cc.name AS Manager_name, 1 AS LevelOf, c.CompanyStoreID 
     FROM @CompanyEmployees    c 
      LEFT OUTER JOIN @CompanyEmployees cc ON c.reports_to_id=cc.id 
     WHERE c.reports_to_id IS NULL 
    UNION ALL 
     SELECT 
      s.id, s.name, s.reports_to_id, t.id, t.name, t.LevelOf+1, s.CompanyStoreID 
     FROM StaffTree     t 
      INNER JOIN @CompanyEmployees s ON t.id=s.reports_to_id 
) 
SELECT 
    c.id AS CompanyID, c.name AS CompanyName 
     ,g.id AS CompanyGroupID, g.name AS CompanyName 
     ,s.id AS CompanyStoreID, s.name AS CompanyStoreName 
     ,t.id AS EmployeeID, t.name as EmployeeName, t.Manager_id, t.Manager_name, t.LevelOf 
    FROM @Company    c 
     LEFT JOIN @CompanyGroup g ON c.id=g.CompanyID 
     LEFT JOIN @CompanyStore s ON g.id=s.CompanyGroupID 
     LEFT JOIN StaffTree  t ON s.id=t.CompanyStoreID 
    ORDER BY c.name,g.name,s.name,s.ID,t.LevelOf,t.name 

ВЫВОД:

CompanyID CompanyName CompanyGroupID CompanyName CompanyStoreID CompanyStoreName EmployeeID EmployeeName Manager_id Manager_name LevelOf 
--------- -------------- -------------- ----------- -------------- ---------------- ----------- ------------ ----------- ------------ ------- 
2   Boring Company 3    Electronics 6    FoodStore  18   apple  NULL  NULL   1 
2   Boring Company 3    Electronics 6    FoodStore  20   grape  18   apple  2 
2   Boring Company 3    Electronics 6    FoodStore  19   pear   18   apple  2 
2   Boring Company 4    Food  NULL   NULL    NULL  NULL   NULL  NULL   NULL 
1   Living Things 2    Humans  5    HumansStore  NULL  NULL   NULL  NULL   NULL 
1   Living Things 1    Pets  1    PetsStoreA  1   Jerome  NULL  NULL   1 
1   Living Things 1    Pets  1    PetsStoreA  9   Bill   1   Jerome  2 
1   Living Things 1    Pets  1    PetsStoreA  2   Joe   1   Jerome  2 
1   Living Things 1    Pets  1    PetsStoreA  6   David  2   Joe   3 
1   Living Things 1    Pets  1    PetsStoreA  3   Paul   2   Joe   3 
1   Living Things 1    Pets  1    PetsStoreA  10   Sam   9   Bill   3 
1   Living Things 1    Pets  1    PetsStoreA  5   Daniel  3   Paul   4 
1   Living Things 1    Pets  1    PetsStoreA  8   Helen  6   David  4 
1   Living Things 1    Pets  1    PetsStoreA  7   Ian   6   David  4 
1   Living Things 1    Pets  1    PetsStoreA  4   Jack   3   Paul   4 
1   Living Things 1    Pets  2    PetsStoreB  11   Alan   NULL  NULL   1 
1   Living Things 1    Pets  2    PetsStoreB  13   Abby   11   Alan   2 
1   Living Things 1    Pets  2    PetsStoreB  12   Ally   11   Alan   2 
1   Living Things 1    Pets  3    PetsStoreC  14   Ben   NULL  NULL   1 
1   Living Things 1    Pets  3    PetsStoreC  15   Bill   14   Ben   2 
1   Living Things 1    Pets  3    PetsStoreC  17   Benny  15   Bill   3 
1   Living Things 1    Pets  3    PetsStoreC  16   Bjorn  15   Bill   3 
1   Living Things 1    Pets  4    PetsStoreD  NULL  NULL   NULL  NULL   NULL 

(23 row(s) affected) 

EDIT после редактирования параметров порядка о том, что We would like to see it in tree form.

Вопрос помечен sql-server-2008 и hierarchical-data, а ОП хочет выполнить сложное форматирование для отображения данных. Однако этот тип обработки и отображения не является сферой TSQL и является очень ясным примером того, где язык приложения должен обрабатывать и форматировать плоские данные, предоставленные SQL-запросом. Я предоставил такой запрос, который может быть использован приложением для создания визуального дерева. Также обратите внимание, что простой пример дерева (не более двух детей на одного родителя) может быть не очень реалистичным, и когда для одного родителя существует много детей, отображение будет сложно построить и не приятно для глаз.

+0

Это только одна таблица, которая является рекурсивной (fks для себя?). Это займет у меня некоторое время, но я проседу через это ... я не дал вам никакой информации, потому что я хотел сохранить ее на высоком уровне. Все они соединены суррогатными ключами, я подумал, что это все, что вам нужно. Спасибо, и я вернусь к вам. – Nix

+0

Это бесполезно для меня ... вы используете ту же таблицу? У меня есть 3 ассоциативных таблицы, в которые я присоединяюсь ... – Nix

+0

@Nix, я сказал: «Вы не предоставляете никакой структуры таблицы, так что вот пример рекурсивной обработки CTE древовидной структуры», ключевого слова «образец». если вы ожидаете вырезать и вставить ответ, вам необходимо предоставить ** путь более подробно в вашем вопросе. Если вам действительно нужен ответ на этот вопрос, вы должны предоставить эквивалентные инструкции DECLARE и INSERT для своих таблиц, например, в моем коде выше, а также набор результатов, который вы хотите получить из этих данных образца. кроме того, никакой ответ не может быть тем, что вы хотите, невозможно угадать структуру вашего стола и прочитать ваш разум о том, что вам нужно. –

0

Я считаю, что SQL Server 2008 предлагает новый тип данных, чтобы помочь в этом сценарии. Вот ссылка, которая, я считаю, поможет - http://msdn.microsoft.com/en-us/magazine/cc794278.aspx. Я не видел его в комментариях, поэтому надеюсь, что это поможет.