使用 SQL Server,我有多个表:
作业
aID,
acID,
clientID,
userID,
pos,
dateOn
分配承运人
acID,
clientID,
cName,
isAssignment
用户
userID,
fName
客户
clientID,
cName,
code
每个客户都有多个运营商。每个运营商有 3 个职位需要填补(分配)。
我编写了一个返回正确信息的查询,但它不是在一行上返回具有 3 个不同位置的分配(对于该分配所具有的每个运营商),而是为每个位置和用户返回一行。
这是我的查询:
SELECT DISTINCT
c.code,
c.cName,
ac.cName,
(SELECT fname
FROM assignments
INNER JOIN users ON users.userID = assignments.userID
WHERE pos = 1 AND aID = a.aID) AS [User 1],
(SELECT dateOn
FROM assignments
WHERE pos = 1 AND aID = a.aID) AS [Date Assigned 1],
(SELECT fname
FROM assignments
INNER JOIN users ON users.userID = assignments.userID
WHERE pos = 2 AND aID = a.aID) AS [User 2],
(SELECT dateOn
FROM assignments
WHERE pos = 2 AND aID = a.aID) AS [Date Assigned 2],
(SELECT fname
FROM assignments
INNER JOIN users ON users.userID = assignments.userID
WHERE pos = 3 AND aID = a.aID) AS [User 3],
(SELECT dateOn
FROM assignments
WHERE pos = 3 AND aID = a.aID) AS [Date Assigned 3]
FROM
clients c
INNER JOIN
assignments a ON a.clientID = c.clientID
INNER JOIN
assignmentCarriers ac ON ac.acID = a.acID
WHERE
isAssignment = 'True'
AND c.active = 'True'
ORDER BY
c.cName
返回:
HDPT Home Depot R+L Domestic Phil Brown 4/1/2023 Null Null Null Null
HDPT Home Depot R+L INTL Phil Brown 5/12/2000 Null Null Null Null
HDPT Home Depot R+L Domestic Null Null Mark Twain 1/22/15 Null Null
HDPT Home Depot R+L INTL Null Null Jen Gump 11/12/12 Null Null
HDPT Home Depot R+L Domestic Null Null Null Null Rob Mills 2/2/12
HDPT Home Depot R+L INTL Null Null Null Null John Smith 12/2/22
所需的输出应该类似于:
HDPT Home Depot R+L Domestic Phil Brown 4/1/2023 Mark Twain 1/22/15 Rob Mills 2/2/12
HDPT Home Depot R+L INTL Phil Brown 5/12/2000 Jen Gump 11/12/12 John Smith 12/2/22
我该如何实现这个目标?谢谢你。
看起来您对使用 SQL 还很陌生,所以让我们从一些基础知识开始。
DECLARE @Jobs TABLE (JobID INT IDENTITY, CompanyName NVARCHAR(50), CompanyID INT);
DECLARE @Users TABLE (UserID INT IDENTITY, FirstName NVARCHAR(50), LastName NVARCHAR(50), JobID INT);
INSERT INTO @Jobs (CompanyName, CompanyID) VALUES ('Home Depot', 123), ('Home Depot', 123), ('Home Depot', 123);
INSERT INTO @Users (FirstName, LastName, JobID) VALUES ('Michael', 'Mark', 1), ('Jon', 'Smith', 2), ('Louise', 'Manfield', 3);
这些是表变量,定义了两个虚拟对象,我们可以用它来做一些演示。在大多数情况下,我们可以像使用实际的表格一样使用它们。
首先我们将获取所有用户:
SELECT UserID, FirstName, LastName, JobID
FROM @Users;
用户ID | 名字 | 姓氏 | 职位ID |
---|---|---|---|
1 | 迈克尔 | 马克 | 1 |
2 | 乔恩 | 史密斯 | 2 |
3 | 路易丝 | 曼菲尔德 | 3 |
我们可以在
SELECT
语句中通过列名称简单地引用表中的列。现在,我们想知道哪些用户属于哪个职位。我们知道这种关系是由 JobID
和 Jobs
表上的 Users
列定义的。我们还使用 ALIAS
(u 和 j)来引用表,因为它们可以(并且确实)具有匹配的列名称
SELECT u.UserID, u.FirstName, u.LastName, u.JobID, j.CompanyID, j.CompanyName
FROM @Users u
INNER JOIN @Jobs j
ON u.JobID = j.JobID
用户ID | 名字 | 姓氏 | 职位ID | 公司ID | 公司名称 |
---|---|---|---|---|---|
1 | 迈克尔 | 马克 | 1 | 123 | 家得宝 |
2 | 乔恩 | 史密斯 | 2 | 123 | 家得宝 |
3 | 路易丝 | 曼菲尔德 | 3 | 123 | 家得宝 |
现在我们已经了解了基础知识,我们可以解决您的实际问题。您想要一份为每家公司工作的人员名单,但排成一行。
您列出了 SQL-Server 2005,我真的希望这是一个错误。在新版本中有很多方法可以做到这一点。
如果您有已知数量的位置可以执行此操作,则只需加入该表三次,每次都强制执行您想要的关联方式:
SELECT DISTINCT CompanyID, u1.FirstName, u1.LastName, u2.FirstName, u2.LastName, u3.FirstName, u3.LastName
FROM @Jobs J
INNER JOIN @Users u1
ON u1.UserID = 1
INNER JOIN @Users u2
ON u2.UserID = 2
INNER JOIN @Users u3
ON u3.UserID = 3
公司ID | 名字 | 姓氏 | 名字 | 姓氏 | 名字 | 姓氏 |
---|---|---|---|---|---|---|
123 | 迈克尔 | 马克 | 乔恩 | 史密斯 | 路易丝 | 曼菲尔德 |
当您编写查询时,您通常会按集合进行工作。在本例中,您要求获取 jobs 表的所有行,这就是您所得到的返回值。任何查询的开始都可能是这样的列表,然后您分支以获取具有其他信息的其他对象,但每个对象将构成一行,直到您开始执行某些聚合。在这种情况下,您想要聚合一个字符串。评论中的一些人提到了
STRING_AGG
功能,但距离 2005 年的情况还差得很远。