我正在使用SQL Server,我很难尝试从我想要的SELECT
查询中获取结果。我尝试过加入不同的命令并使用子查询,但没有什么能按我想要的方式工作。以这个人为计算机上可能安装的具有不同版本级别的软件应用程序为例。
我需要使用JOIN
执行WHERE
,但出于某种原因,我无法获得我想要的结果。
也许我正在查看我的数据错误,我不太清楚为什么我不能让它工作。
申请表
ID Name
1 Word
2 Excel
3 Powerpoint
软件表(包含不同应用程序的版本信息)
ID ApplicationID Version
1 1 2003
2 1 2007
3 2 2003
4 2 2007
5 3 2003
6 3 2007
Software_Computer 联结表
ID SoftwareID ComputerID
1 1 1
2 4 1
3 2 2
4 5 2
计算机表
ID ComputerName
1 Name1
2 Name2
我想要一个查询,我可以在选择特定计算机的地方运行,以显示软件版本和应用程序的内容,但我也希望它显示它没有的应用程序(版本为{{1}因为它上面没有那个软件)
NULL
我想要以下结果集
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN Software_Computer
ON Computer.ID = Software_Computer.ComputerID
JOIN Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = 1
但我得到了
ComputerName Name Version
Name1 Word 2003
Name1 Excel 2007
Name1 Powerpoint NULL
我认为Results
ComputerName Name Version
Name1 Word 2003
Name1 Excel 2007
将包含应用程序表中的所有结果,即使它们与计算机无关。我错过了什么/做错了什么?
答案 0 :(得分:13)
使用LEFT JOIN
或RIGHT JOIN
时,无论是将过滤器放在WHERE
还是放入JOIN
,都会有所不同。
请参阅我之前写的类似问题的答案:
What is the difference in these two queries as getting two different result set?
简而言之:
WHERE
子句中(与您一样,与该计算机无关的结果将被完全过滤掉JOIN
,则与该计算机无关的结果会显示在查询结果中,仅显示NULL
个值
- >这就是你想要的答案 1 :(得分:8)
您期望的第三行(使用Powerpoint的那一行)被Computer.ID = 1
条件过滤掉(尝试使用Computer.ID = 1 or Computer.ID is null
运行查询,看看会发生什么)。
但是,删除这个条件没有意义,因为毕竟我们想要一个给定计算机的列表。
我看到的唯一解决方案是在原始查询和新查询之间执行UNION,该查询检索在该计算机上找到不的应用程序列表。
查询可能如下所示:
DECLARE @ComputerId int
SET @ComputerId = 1
-- your original query
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN dbo.Software_Computer
ON Computer.ID = Software_Computer.ComputerID
JOIN dbo.Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN dbo.Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = @ComputerId
UNION
-- query that retrieves the applications not installed on the given computer
SELECT Computer.ComputerName, Application.Name, NULL as Version
FROM Computer, Application
WHERE Application.ID not in
(
SELECT s.ApplicationId
FROM Software_Computer sc
LEFT JOIN Software s on s.ID = sc.SoftwareId
WHERE sc.ComputerId = @ComputerId
)
AND Computer.id = @ComputerId
答案 2 :(得分:2)
试试这个
DECLARE @Application TABLE(Id INT PRIMARY KEY, NAME VARCHAR(20))
INSERT @Application ( Id, NAME )
VALUES ( 1,'Word' ), ( 2,'Excel' ), ( 3,'PowerPoint' )
DECLARE @software TABLE(Id INT PRIMARY KEY, ApplicationId INT, Version INT)
INSERT @software ( Id, ApplicationId, Version )
VALUES ( 1,1, 2003 ), ( 2,1,2007 ), ( 3,2, 2003 ), ( 4,2,2007 ),( 5,3, 2003 ), ( 6,3,2007 )
DECLARE @Computer TABLE(Id INT PRIMARY KEY, NAME VARCHAR(20))
INSERT @Computer ( Id, NAME )
VALUES ( 1,'Name1' ), ( 2,'Name2' )
DECLARE @Software_Computer TABLE(Id INT PRIMARY KEY, SoftwareId int, ComputerId int)
INSERT @Software_Computer ( Id, SoftwareId, ComputerId )
VALUES ( 1,1, 1 ), ( 2,4,1 ), ( 3,2, 2 ), ( 4,5,2 )
SELECT Computer.Name ComputerName, Application.Name ApplicationName, MAX(Software2.Version) Version
FROM @Application Application
JOIN @Software Software
ON Application.ID = Software.ApplicationID
CROSS JOIN @Computer Computer
LEFT JOIN @Software_Computer Software_Computer
ON Software_Computer.ComputerId = Computer.Id AND Software_Computer.SoftwareId = Software.Id
LEFT JOIN @Software Software2
ON Software2.ID = Software_Computer.SoftwareID
WHERE Computer.ID = 1
GROUP BY Computer.Name, Application.Name
答案 3 :(得分:1)
您需要执行LEFT JOIN
。
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN dbo.Software_Computer
ON Computer.ID = Software_Computer.ComputerID
LEFT JOIN dbo.Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN dbo.Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = 1
以下是解释:
表A和表的左外连接(或简称左连接)的结果 B总是包含“左”表(A)的所有记录,即使是 join-condition在“右”表中找不到任何匹配的记录 (B)。这意味着如果ON子句匹配B中的0(零)记录, 连接仍会在结果中返回一行 - 但每个中都有NULL 来自B的列。这意味着左外连接返回所有 左表中的值加上右表中的匹配值 (如果没有匹配的连接谓词,则为NULL)。如果是正确的表 返回一行,左表返回多个匹配的行 对于它,右表中的值将重复 左表上的不同行。从Oracle 9i开始,LEFT OUTER 可以使用JOIN语句以及(+)。
答案 4 :(得分:1)
SELECT p.Name, v.Name
FROM Production.Product p
JOIN Purchasing.ProductVendor pv
ON p.ProductID = pv.ProductID
JOIN Purchasing.Vendor v
ON pv.BusinessEntityID = v.BusinessEntityID
WHERE ProductSubcategoryID = 15
ORDER BY v.Name;
答案 5 :(得分:0)
试试这个工作正常......
SELECT computer.NAME, application.NAME,software.Version FROM computer LEFT JOIN software_computer ON(computer.ID = software_computer.ComputerID)
LEFT JOIN software ON(software_computer.SoftwareID = Software.ID) LEFT JOIN application ON(application.ID = software.ApplicationID)
where computer.id = 1 group by application.NAME UNION SELECT computer.NAME, application.NAME,
NULL as Version FROM computer, application WHERE application.ID not in ( SELECT s.applicationId FROM software_computer sc LEFT JOIN software s
on s.ID = sc.SoftwareId WHERE sc.ComputerId = 1 )
AND computer.id = 1
答案 6 :(得分:0)
选择C.ComputerName,S.Version,A.Name 来自Computer C内部加入Software_Computer SC 在C.Id = SC.ComputerId 内连接软件S. 在SC.SoftwareID = S.Id上 内连接应用程序A. 在S.ApplicationId = A.Id;
答案 7 :(得分:0)
SELECT Computer.Computer_Name, Application1.Name, Max(Soft.[Version]) as Version1
FROM Application1
inner JOIN Software
ON Application1.ID = Software.Application_Id
cross join Computer
Left JOIN Software_Computer
ON Software_Computer.Computer_Id = Computer.ID and Software_Computer.Software_Id = Software.Id
Left JOIN Software as Soft
ON Soft.Id = Software_Computer.Software_Id
WHERE Computer.ID = 1
GROUP BY Computer.Computer_Name, Application1.Name