创建SQL查询以显示客户端及其联系人

时间:2014-10-17 08:39:09

标签: sql-server select union-all

我正在使用SQL Server 2008.我有两个表:

客户

CREATE TABLE Clients 
(
  Id int primary key, 
  Name varchar(20), 
  ParentId int
);

INSERT INTO Clients(Id, Name, ParentId) VALUES (1, 'A', 1);
INSERT INTO Clients(Id, Name, ParentId) VALUES (2, 'B', 2);
INSERT INTO Clients(Id, Name, ParentId) VALUES (3, 'AA', 1);
INSERT INTO Clients(Id, Name, ParentId) VALUES (4, 'BB', 2);
INSERT INTO Clients(Id, Name, ParentId) VALUES (5, 'C', 1);

此表包含所有客户的信息,其中一些有父公司/客户,ParentId显示。如果它与Id匹配,则意味着这些客户端是层次结构中的顶级公司。

联系人

CREATE TABLE Contacts 
(
  Id int primary key, 
  Name varchar(20),
  Email varchar(20),
  ClientId int
);

INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (1, 'Bob', 'Bob@A.com', 1);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (2, 'John', 'John@A.com', 1);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (3, 'Charlie', 'Charlie@B.com', 2);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (4, 'Peter', 'Peter@AA.com', 3);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (5, 'Chris', 'Chris@AA.com', 3);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (6, 'Neil', 'Neil@BB.com', 4);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (7, 'Grant', 'Grant@C.com', 5);
INSERT INTO Contacts(Id, Name, Email, ClientId) VALUES (8, 'Cher', 'Cher@C.com', 5);

此表包含特定客户端的所有联系人(ClientId显示它)。

我需要有一个列表,其中包含客户和特定客户的所有联系人以及他母公司的所有联系人。

例如

ClientName | ContactName  | ContactEmail
   AA      |              |
           |     Bob      |   Bob@A.com
           |     John     |   John@A.com
           |     Peter    |  Peter@AA.com
           |     Chris    |  Chris@AA.com
    C      |              |
           |     Grant    |  Grant@C.com
           |     Cher     |   Cher@C.com

我设法编写了一个SQL查询,它只为一个客户端提供结果,但我希望它返回多个客户端。如上所示向客户(第3和第5)及其联系人显示。

SELECT 
    C.Name, ' ', ' ' 
FROM 
    Clients C 
WHERE 
    C.Id = 3

UNION ALL

SELECT 
    ' ', Co.Name, Co.Email 
FROM
    Contacts Co
WHERE 
    ClientId = 3 OR (ClientId = (SELECT ParentId FROM Clients WHERE Id = 3)) 

3 个答案:

答案 0 :(得分:1)

没有SQL格式。

select
    Cli.Name,
    Co.Name,
    Co.Email
from Clients Cli
left join Contacts Co on
    Co.ClientId in(Cli.Id,Cli.ParentId)
order by
    1,2

使用Formatting ..你真的应该在SQL之外进行格式化。但这是一种方法

select
    CASE WHEN cls <> 1 THEN '' ELSE CLI_NAME END CLIENT_NAME,
    CO_NAME CONTACT_NAME,
    CO_EMAIL CONTACT_EMAIL
from (
    select
    ROW_NUMBER() OVER (
        PARTITION BY
            T.CLI_NAME
        ORDER BY    
            T.CO_NAME
    ) cls,
    CLI_NAME,
    CO_NAME,
    CO_EMAIL
    from (
        select
        Cli.Name CLI_NAME,
        '' CO_NAME,
        '' CO_EMAIL
        from Clients Cli
        WHERE 
            Cli.id in (3,5)
        UNION ALL
        select
            Cli.Name,
            Co.Name,
            Co.Email
        from Clients Cli
        left join Contacts Co on
            Co.ClientId in(Cli.Id,Cli.ParentId)
        WHERE 
            Cli.id in (3,5)
    ) T
) T
order by
    CLI_NAME,
    CO_NAME

答案 1 :(得分:0)

如果客户只有一家母公司并且这不是递归的,那么您也可以使用UNION获取母公司数据。我会在报告工具中根据需要格式化数据,而不是尝试在SQL中执行此操作。

SELECT
  Clients.Name AS ClientName,
  Contacts.Name AS ContactName,
  Contacts.Email AS ContactEmail
FROM
  Clients
JOIN
  Contacts
ON
  Clients.Id = Contacts.ClientId

UNION

SELECT
  Clients.Name AS ClientName,
  Contacts.Name AS ContactName,
  Contacts.Email AS ContactEmail
FROM
  Clients
JOIN
  Contacts
ON
  Clients.ParentId = Contacts.ClientId

ORDER BY
  ClientName,
  ContactName

答案 2 :(得分:0)

这是一个通用解决方案(没有格式化),允许孩子拥有子/层次结构深度&gt; 1

  WITH parentcte (id,parentid,name)
  AS (SELECT c1.id,
 c1.parentid,name
  FROM clients c1
 WHERE c1.id=3 -- you can remove the where clause if you want list of all clients
  UNION ALL
  SELECT
    c.id,c.parentid,parentcte.name
  FROM parentcte
  JOIN clients c
    ON 
    c.id=parentcte.parentid where c.id != c.parentid)
    select  distinct p.name,con.name,email from parentcte p
    join contacts con on con.ClientId=p.id or con.clientid=p.parentid