从一个表中选择与客户关联的工单记录或另一表中的客户子项
Posted
技术标签:
【中文标题】从一个表中选择与客户关联的工单记录或另一表中的客户子项【英文标题】:Select Ticket records from one table that are associated with a Customer or the Customers children in another table 【发布时间】:2016-04-15 11:28:30 【问题描述】:假设我有一个包含所有客户记录的表。 每条记录都有一个唯一的 ID、名称和可能的父记录 ID。
(如果父母可以有多个孩子但孩子只能有一个父母。也没有祖父记录,所以父母可能没有父母,孩子可能没有孩子)
客户
+-----+------------+----------+
| ID | Name | ParentID |
+-----+------------+----------+
| 100 | Customer A | |
| 101 | Customer B | |
| 102 | Customer C | 100 |
| 103 | Customer D | 100 |
| 104 | Customer E | 101 |
+-----+------------+----------+
从这个示例中可以看出,我有 5 条唯一的客户记录,其中 C 和 D 是 A 的子项,E 是 B 的子项。
现在我有一个表格,其中包含这些客户提出的所有票证。 每张工单都有唯一的 ID、描述和父客户 ID。
门票
+-----+-------------+----------+
| ID | Description | ParentID |
+-----+-------------+----------+
| 500 | Ticket A | 100 |
| 501 | Ticket B | 100 |
| 502 | Ticket C | 102 |
| 503 | Ticket D | 102 |
| 504 | Ticket E | 103 |
| 505 | Ticket F | 101 |
| 506 | Ticket G | 104 |
| 507 | Ticket H | 101 |
+-----+-------------+----------+
目标
我将获得一个客户 ID,需要选择属于该记录的所有工单。 如果记录有孩子,我还需要属于这些记录的票。 如果记录是子记录,我对其父记录不感兴趣。示例 1
我的 ID 为 100。这是客户 A,有两个孩子,C 和 D。 作为我选择的结果,我希望得到以下结果:
票 A - 直接属于 ID 100 票 B - 直接属于 ID 100 票 C - 属于 ID 102,100 岁的孩子 票 D - 属于 ID 102,100 岁的孩子 票 E - 属于 ID 103,100 岁的孩子示例 2
我的 ID 为 104。这是客户 E,一个子记录。 作为我选择的结果,我希望得到以下结果:
票证 G - 直接属于 ID 104我不会期待任何进一步的记录,因为该记录是一个子记录,因此没有子记录,而且我不会向上查看父记录。
我被困在哪里......
获取属于一个 ID 的门票很容易:
SELECT
tickets.Description
FROM
Tickets AS tickets
LEFT JOIN
Customers AS customers ON
tickets.ParentID = customers.ID
WHERE
customers.ID = 100
我无法获得属于儿童的门票。
似乎我首先必须请求属于给定 ID 的客户,然后获取 ParentID 与给定 ID 匹配的所有子客户,然后最后请求属于这些记录中的任何一个的门票。
很遗憾,我不知道从哪里开始,需要一些帮助。
如果相关,我使用的是 SQL Server 2008 R2。
【问题讨论】:
将customers.ID = 100
移动到ON
子句以获得真正的左连接结果!
【参考方案1】:
您可能需要使用recursive common table expression 来遍历祖先并获取所有相关记录:
DECLARE @CustomerID INT = 100;
-- SAMPLE DATA FOR CUSTOMERS
DECLARE @Customers TABLE (ID INT, Name VARCHAR(255), ParentID INT);
INSERT @Customers (ID, Name, ParentID)
VALUES
(100, 'Customer A', NULL),
(101, 'Customer B', NULL),
(102, 'Customer C', 100),
(103, 'Customer D', 100),
(104, 'Customer E', 101);
-- SAMPLE DATA FOR TICKETS
DECLARE @Tickets TABLE (ID INT, Name VARCHAR(255), ParentID INT);
INSERT @Tickets (ID, Name, ParentID)
VALUES
(500, 'Ticket A', 100),
(501, 'Ticket B', 100),
(502, 'Ticket C', 102),
(503, 'Ticket D', 102),
(504, 'Ticket E', 103),
(505, 'Ticket F', 101),
(506, 'Ticket G', 104),
(507, 'Ticket H', 101);
-- USE RECURSIVE CTE TO LOOP THROUGH HIERARCHY AND GET ALL ANCESTORS
WITH RecursiveCustomers AS
( SELECT c.ID, c.Name, c.ParentID
FROM @Customers AS c
UNION ALL
SELECT rc.ID, rc.Name, c.ParentID
FROM RecursiveCustomers AS rc
INNER JOIN @Customers AS c
ON rc.ParentID = c.ID
)
SELECT t.ID, t.Name, t.ParentID
FROM @Tickets AS t
INNER JOIN RecursiveCustomers AS rc
ON rc.ID = t.ParentID
WHERE rc.ParentID = @CustomerID OR (rc.ID = @CustomerID AND rc.ParentID IS NULL);
100 分的结果
+-----+-------------+----------+
| ID | Description | ParentID |
+-----+-------------+----------+
| 500 | Ticket A | 100 |
| 501 | Ticket B | 100 |
| 502 | Ticket C | 102 |
| 503 | Ticket D | 102 |
| 504 | Ticket E | 103 |
+-----+-------------+----------+
结果为 104
+-----+-------------+----------+
| ID | Description | ParentID |
+-----+-------------+----------+
| 506 | Ticket G | 104 |
+-----+-------------+----------+
【讨论】:
哇,太棒了。非常感谢。我会去自学到底为什么会这样;-)【参考方案2】:Select tickets.Description
FROM
Tickets AS tickets
LEFT JOIN
Customers ON
customers.ID= tickets.ParentID
OR
customers.ParentID =tickets.ParentID
WHERE
Tickets.ParentID = 100
【讨论】:
这返回了“票 A;票 A;票 A;票 B;票 B;票 B;” 6 行不正确【参考方案3】:虽然 GarethD 提供的演示在演示中运行良好(起初我认为它适用于实时数据)但我在实时数据中得到了奇怪的结果,其中属于父级的票证每次重复 4 次,尽管行与孩子只出现过一次。
在我的无知和无法解决上述问题的情况下,我使用了另一种效果很好的方法,所以我想我会把它留在这里作为替代方案。
首先我选择父记录和子记录并将它们存储在一个表中:
DECLARE @CUSTOMERS TABLE (
ID BIGINT,
PARENTID BIGINT,
NAME VARCHAR(MAX)
)
INSERT INTO @CUSTOMERS(ID, PARENTID, NAME)
SELECT
id,
parent_id,
name
FROM [customer_table]
WHERE id = '194' OR parent_id = '194';
现在我可以正常加入此表以选择正确的门票:
SELECT
customer.[NAME],
ticket.[id],
ticket.[description],
FROM [ticket_table] AS ticket
LEFT JOIN @CUSTOMERS AS customer
ON ticket.[id] = customer.[ID]
WHERE
ticket.[id] = customer.[ID];
这会产生正确数量的票,而且速度似乎足够快。希望它可以帮助某人。
【讨论】:
以上是关于从一个表中选择与客户关联的工单记录或另一表中的客户子项的主要内容,如果未能解决你的问题,请参考以下文章
Sequelize - 如何从一个表中获取未被另一表关联的条目