Пожалуйста, не указывайте мне статью о том, как создавать древовидные структуры или CTE в SQL, я читал много !!! Я думаю, что это может быть не так сложно для T-SQL в глубине души, но это определенно трудно для меня :).
Вот ситуация, я должен создать отчет, который выглядит следующим образом:
альтернативный текст http://img85.imageshack.us/img85/6372/70337249.png
Это прекрасно работает, когда для параметра моей хранимой процедуры (SQL Server sproc) установлено значение «Все», поскольку это просто захватывает все данные, и конечный пользователь может развернуть / свернуть элементы, чтобы увидеть иерархию. Проблема возникает, когда, например, я запускаю отчет и выбираю имя, например, в этом случае «Кевин Бикинг» видит результат:
альтернативный текст http://img69.imageshack.us/img69/8398/46964880.png
Проблема в том, что я получаю только прямое сообщение о Кевине, но мне действительно нужно увидеть все подчиненные директивы. Например, на первом изображении я хотел бы, чтобы в моем отчете отображались все люди ниже Кевина, ниже Кельвина, ниже Тима и т. Д. И т. Д.
Я понимаю проблему, но не знаю, как с ней справиться в T-SQL. Вот моя хранимая процедура:
CREATE PROCEDURE [dbo].[rptContactsHierarchy]
@ContactID varchar(100)='All'
AS
BEGIN
SET NOCOUNT ON;
SELECT
c1.id AS EmployeeID,
c2.id as ManagerID,
c1.first_name + ' ' + c1.last_name AS [EmployeeName],
c1.title AS Title,
c2.first_name + ' ' + c2.last_name AS [ReportsTo]
FROM
Contacts c1
INNER JOIN
Contacts c2
ON
c1.reports_to_id = c2.id
WHERE
c1.deleted=0
AND (@ContactID='All' OR (c2.first_name + ' ' + c2.last_name = @ContactID OR (c1.first_name + ' ' + c1.last_name = @ContactID)))
END
Sproc работает нормально, в нем нет ошибок, но мой вопрос состоит в том, чтобы использовать мои поля, которые я перечислил здесь, как я могу изменить его, чтобы получать прямые отчеты под другим именем, как я описал выше. По сути, поле EmployeeName каждый раз является верхним уровнем (то есть параметром отчета), а псевдоним ReportsTo - это поле в отчете, которое вы видите на изображении.
У меня нет вопроса об отчете SSRS, просто о том, как изменить запрос так, чтобы в этом случае я выбрал Кевина Бикинга и передал его моей хранимой процедуре. В настоящее время его возвращает только прямой сотрудник Kelvin Squires. Но я хочу, чтобы это вернуло не только Кельвина, но и всех людей, которые подчиняются Кельвину, и всех людей, которые могут быть начальниками при Кельвине, но также имеют прямые сообщения.
Любая помощь очень ценится. Спасибо за ваше время!
Редактировать часть
Я использую sql server 2005. Кто-то спросил определение таблицы, обратите внимание, я не создавал эту таблицу, это система на основе CRM, которая генерируется автоматически:
USE [sugarcrm]
GO
/****** Object: Table [dbo].[contacts] Script Date: 07/22/2010 10:44:31 ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING OFF
GO
CREATE TABLE [dbo].[contacts](
[id] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
[date_entered] [datetime] NULL,
[date_modified] [datetime] NULL,
[modified_user_id] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[created_by] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[description] [text] COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[deleted] [bit] NULL DEFAULT ('0'),
[assigned_user_id] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[team_id] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[salutation] [varchar](5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[first_name] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[last_name] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[title] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[department] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[do_not_call] [bit] NULL DEFAULT ('0'),
[phone_home] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[phone_mobile] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[phone_work] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[phone_other] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[phone_fax] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[primary_address_street] [varchar](150) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[primary_address_city] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[primary_address_state] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[primary_address_postalcode] [varchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[primary_address_country] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[alt_address_street] [varchar](150) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[alt_address_city] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[alt_address_state] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[alt_address_postalcode] [varchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[alt_address_country] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[assistant] [varchar](75) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[assistant_phone] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[lead_source] [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[reports_to_id] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[birthdate] [datetime] NULL,
[portal_name] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[portal_active] [bit] NOT NULL DEFAULT ('0'),
[portal_password] [varchar](32) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[portal_app] [varchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[campaign_id] [varchar](36) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [pk_contacts] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
Решение
С помощью вас, ребята, было мое решение
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[rptContactsHierarchy]
@ContactID varchar(100)='All'
AS
BEGIN
SET NOCOUNT ON;
--grab id of @contactid
DECLARE @Test varchar(36)
SELECT @Test = (SELECT id FROM contacts c1 WHERE c1.first_name + ' ' + c1.last_name = @ContactID)
;WITH StaffTree AS
(
SELECT
c.id,
c.Title,
c.first_name,
c.last_name,
c.reports_to_id,
c.reports_to_id as Manager_id,
cc.first_name AS Manager_first_name,
cc.last_name as Manager_last_name,
cc.first_name + ' ' + cc.last_name AS [ReportsTo],
c.first_name + ' ' + c.last_name as EmployeeName,
1 AS LevelOf
FROM Contacts c
LEFT OUTER JOIN Contacts cc ON c.reports_to_id=cc.id
WHERE c.id=@Test OR (@Test IS NULL AND c.reports_to_id IS NULL)
UNION ALL
SELECT
s.id,
s.Title,
s.first_name,
s.last_name,
s.reports_to_id,
t.id,
t.first_name,
t.last_name,
t.first_name + ' ' + t.last_name,
s.first_name + ' ' + s.last_name,
t.LevelOf+1
FROM StaffTree t
INNER JOIN Contacts s ON t.id=s.reports_to_id
WHERE s.reports_to_id=@Test OR @Test IS NULL OR t.LevelOf>1
)
SELECT * FROM StaffTree
END