Sql 查找相关表中是否存在某些内容

Sql 查找相关表中是否存在某些内容,sql,sql-server,Sql,Sql Server,我有一张桌子的员工和一张桌子的销售人员,他们是一对多的关系。员工将包含姓名、电子邮件、id等字段,销售将包括国家、销售数量、员工id等信息 我现在要做的是为每个员工查找sales表中是否存在特定国家/地区的条目 我的输出应该类似于 Employee.name,Employee.email,出售给加拿大 在“销往加拿大”中,我只想输入1或0,这取决于每个员工在销售中是否有符合特定国家条件的条目 我已经尝试过的是: SELECT emp.name ,emp.email

我有一张桌子的员工和一张桌子的销售人员,他们是一对多的关系。员工将包含姓名、电子邮件、id等字段,销售将包括国家、销售数量、员工id等信息

我现在要做的是为每个员工查找sales表中是否存在特定国家/地区的条目

我的输出应该类似于

Employee.name,Employee.email,出售给加拿大

在“销往加拿大”中,我只想输入1或0,这取决于每个员工在销售中是否有符合特定国家条件的条目

我已经尝试过的是:

    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;