Sql 查找相关表中是否存在某些内容
我有一张桌子的员工和一张桌子的销售人员,他们是一对多的关系。员工将包含姓名、电子邮件、id等字段,销售将包括国家、销售数量、员工id等信息 我现在要做的是为每个员工查找sales表中是否存在特定国家/地区的条目 我的输出应该类似于 Employee.name,Employee.email,出售给加拿大 在“销往加拿大”中,我只想输入1或0,这取决于每个员工在销售中是否有符合特定国家条件的条目 我已经尝试过的是:Sql 查找相关表中是否存在某些内容,sql,sql-server,Sql,Sql Server,我有一张桌子的员工和一张桌子的销售人员,他们是一对多的关系。员工将包含姓名、电子邮件、id等字段,销售将包括国家、销售数量、员工id等信息 我现在要做的是为每个员工查找sales表中是否存在特定国家/地区的条目 我的输出应该类似于 Employee.name,Employee.email,出售给加拿大 在“销往加拿大”中,我只想输入1或0,这取决于每个员工在销售中是否有符合特定国家条件的条目 我已经尝试过的是: SELECT emp.name ,emp.email
SELECT emp.name
,emp.email
,(SELECT COUNT(1) FROM sales sa JOIN employee emp ON emp.ID = sales.employeeID
WHERE sales.country = 'Canada') as "Sold to Canada"
FROM employee emp
这导致“Sald to Canada”中的数字远远大于1,因为我假设它返回已向加拿大销售的员工总数,而不是每个特定员工的信息 您可以使用
案例:
SELECT emp.name,
emp.email,
(CASE WHEN emp.ID IN (SELECT sales.employeeID FROM sales WHERE sales.country = 'Canada') THEN 1 ELSE 0 END) AS [Sold to Canada]
FROM employee emp
这是使用相关子查询直接转换为SQL:-)
给猫剥皮有很多种方法。下面是一个更好的例子:
SELECT emp.name, emp.email, ISNULL( Sold, 0 ) AS [Sold to Canada]
FROM employee AS emp
LEFT JOIN
( SELECT 1 AS Sold, employeeID
FROM sales
WHERE sales.country = 'Canada'
GROUP BY employeeID ) AS CanadaSales
ON emp.ID = CanadaSales.employeeID
评论:
在SELECT
部分中使用相关子查询不是一个好主意,因为这可能会导致查询计划效率低下,从而降低查询性能
更新:
如果您需要返回多个国家/地区的结果,我将使用
评论:
PIVOT
函数需要太多括号。@Alex已经给出了一个很好的答案。但是,如果希望避免子查询,可以使用此解决方案
SELECT MIN(e.Name) AS EmployeeName
, MIN(e.Email) AS Email
, CASE WHEN MIN(EmployeeID) IS NOT NULL THEN 1 ELSE 0 END AS [Sold To Canada]
FROM Employee AS e
LEFT JOIN Sales AS s ON (s.EmployeeID = e.ID AND Country = 'Canada')
GROUP BY e.ID;
哇,这个解决方案太快了!与使用
案例相比,当
执行速度快100倍时,如果我想查看多个国家,我是否可以通过添加更多联接来扩展它?我试过了,似乎效果不错,但我想确保这是正确的方法。
SELECT emp.name, emp.email, ISNULL( Canada, 0 ) AS SoldCanada, ISNULL( Australia, 0 ) AS SoldAustralia /*, ISNULL( [another country], 0 ) AS [Sold Yet another country] */
FROM employee AS emp
LEFT JOIN
( SELECT *
FROM
(
-- List of Country Employees
SELECT 1 AS Sold, employeeID, country
FROM sales
GROUP BY employeeID, country ) AS EmpCountrySales
PIVOT
(
-- For each country present return 1, else NULL
MAX( Sold ) FOR country IN( [Canada], [Australia] /* , [another country] */ )
) AS pvt
) AS EmployeeSales
ON emp.ID = EmployeeSales.employeeID
SELECT MIN(e.Name) AS EmployeeName
, MIN(e.Email) AS Email
, CASE WHEN MIN(EmployeeID) IS NOT NULL THEN 1 ELSE 0 END AS [Sold To Canada]
FROM Employee AS e
LEFT JOIN Sales AS s ON (s.EmployeeID = e.ID AND Country = 'Canada')
GROUP BY e.ID;