获取在SQL

时间:2015-10-13 17:47:55

标签: sql sql-server join

我正在研究三个SQL表,并尝试让所有参与所有三个计划的员工如下:

表:员工

╔════════════╦═══════════╦═══════════╦═══════════╦═══════════╦════════╗
║ EmployeeID ║ FirstName ║ LastName  ║ Birthdate ║ HomeState ║ Gender ║
╠════════════╬═══════════╬═══════════╬═══════════╬═══════════╬════════╣
║          1 ║ John      ║ Doe       ║ 1/1/1978  ║ FL        ║ M      ║
║          2 ║ Jane      ║ Eyre      ║ 4/7/1985  ║ AL        ║ F      ║
║          3 ║ Alexander ║ Hamilton  ║ 6/4/1960  ║ NY        ║ M      ║
║          4 ║ Chris     ║ Smith     ║ 12/5/1990 ║ CA        ║ M      ║
║          5 ║ Emily     ║ Dickinson ║ 3/5/1945  ║ VT        ║ F      ║
╚════════════╩═══════════╩═══════════╩═══════════╩═══════════╩════════╝

表:计划

╔════════╦══════════╦════════════════╗
║ PlanID ║ PlanType ║    PlanName    ║
╠════════╬══════════╬════════════════╣
║      1 ║ Medical  ║ Medical Plan 1 ║
║      2 ║  Dental  ║ Dental Plan 1  ║
║      3 ║ Vision   ║ Vision Plan 1  ║
║      4 ║ Medical  ║ Medical Plan 2 ║
╚════════╩══════════╩════════════════╝    

表: PlanEnrollment

╔══════════════╦════════════╦════════╦═════════════════════╦══════════════════╗
║ EnrollmentID ║ EmployeeID ║ PlanID ║ EnrollmentStartDate ║ ErollmentEndDate ║
╠══════════════╬════════════╬════════╬═════════════════════╬══════════════════╣
║            1 ║          1 ║      1 ║ 1/1/2015            ║ 3/1/2015         ║
║            2 ║          1 ║      2 ║ 1/1/2014            ║ NULL             ║
║            3 ║          2 ║      1 ║ 6/1/2013            ║ 5/1/2015         ║
║            4 ║          3 ║      4 ║ 2/1/2013            ║ NULL             ║
║            5 ║          4 ║      2 ║ 5/3/2015            ║ 7/1/2015         ║
║            6 ║          1 ║      4 ║ 3/2/2015            ║ NULL             ║
╚══════════════╩════════════╩════════╩═════════════════════╩══════════════════╝   

从上表中我试图检索目前参加所有三项医疗,牙科和视力计划的所有员工的名字和姓氏。

怎么做?

6 个答案:

答案 0 :(得分:0)

这应该可以解决问题。我仍然不是SQL专家。我可能会遗漏一些内容。

SELECT * FROM `PlanEnrollment`,`Employee` 
WHERE COUNT(`PlanEnrollment`.`EmployeeID`) = 3
AND `PlanEnrollment`.`PlanID` != 4
GROUP BY `PlanEnrollment`.`EmployeeID`
JOIN `Employee` ON `PlanEnrollment`.`EmployeeID` = `Employee`.`EmployeeID`

答案 1 :(得分:0)

这应该

SELECT e.firstname, 
       e.lastname
FROM Employee e 
WHERE NOT EXISTS (SELECT PlanID
                  FROM Plan
                  WHERE PlanType IN ('Medical', 'Dental', 'Vision')
                  EXCEPT 
                  SELECT PlanID
                  FROM PlanEnrollment pe
                  WHERE pe.EmployeeID= e.EmployeeID)

简而言之,对于每个员工,这将找到您感兴趣的计划ID列表,减去员工注册的计划。如果减法为空,则表示员工已注册所有计划并且NOT EXISTS将为您返回此员工。

答案 2 :(得分:0)

LiveDemo

工作原理:

  1. 获取当前有效的所有员工计划
  2. 左侧加入计划表3次(视觉,牙科,医疗)
  3. 总结一下
  4. 选择有3
  5. 的员工
  6. 加入Employee表并获取个人数据
  7. 查询:

    WITH cte AS
    (
      SELECT EmployeeId, 
        [dental] = SUM(IIF(p.PlanId IS NULL,0, 1)),
        [vision] = SUM(IIF(p2.PlanId IS NULL,0, 1)),
        [medical] = SUM(IIF(p3.PlanId IS NULL,0, 1))
      FROM #PlanEnrollment pe
      LEFT JOIN #Plan p
        ON pe.PlanId = p.PlanID
        AND p.PlanType LIKE 'Dental'
      LEFT JOIN #Plan p2
        ON pe.PlanId = p2.PlanID
        AND p2.PlanType LIKE 'Vision'
      LEFT JOIN #Plan p3
        ON pe.PlanId = p3.PlanID
       AND p3.PlanType LIKE 'Medical'
      WHERE GETDATE() >= EnrollmentStartDate 
        AND GETDATE() <= ISNULL(ErollmentEndDate, '2099-01-01')
      GROUP BY EmployeeId
    )
    SELECT e.FirstName, e.LastName
    FROM cte c
    JOIN  #Employee e 
      ON c.EmployeeID = e.EmployeeId
    WHERE [dental] > 0 AND [vision] > 0 AND [medical] > 0;
    

    数据:

    CREATE TABLE #Employee(
      EmployeeID INTEGER  NOT NULL
      ,FirstName  VARCHAR(90) NOT NULL
      ,LastName   VARCHAR(90) NOT NULL
      ,Birthdate  DATE  NOT NULL
      ,HomeState  VARCHAR(20) NOT NULL
      ,Gender     VARCHAR(10) NOT NULL
    );
    INSERT INTO #Employee(EmployeeID,FirstName,LastName,Birthdate,HomeState,Gender) VALUES (1,'John','Doe','1/1/1978','FL','M');
    INSERT INTO #Employee(EmployeeID,FirstName,LastName,Birthdate,HomeState,Gender) VALUES (2,'Jane','Eyre','4/7/1985','AL','F');
    INSERT INTO #Employee(EmployeeID,FirstName,LastName,Birthdate,HomeState,Gender) VALUES (3,'Alexander','Hamilton','6/4/1960','NY','M');
    INSERT INTO #Employee(EmployeeID,FirstName,LastName,Birthdate,HomeState,Gender) VALUES (4,'Chris','Smith','12/5/1990','CA','M');
    INSERT INTO #Employee(EmployeeID,FirstName,LastName,Birthdate,HomeState,Gender) VALUES (5,'Emily','Dickinson','3/5/1945','VT','F');
    
    
    CREATE TABLE #Plan(
      PlanID   INTEGER  NOT NULL
      ,PlanType VARCHAR(70) NOT NULL
      ,PlanName VARCHAR(70) NOT NULL
    );
    INSERT INTO #Plan(PlanID,PlanType,PlanName) VALUES (1,'Medical','Medical Plan 1');
    INSERT INTO #Plan(PlanID,PlanType,PlanName) VALUES (2,'Dental','Dental Plan 1');
    INSERT INTO #Plan(PlanID,PlanType,PlanName) VALUES (3,'Vision','Vision Plan 1');
    INSERT INTO #Plan(PlanID,PlanType,PlanName) VALUES (4,'Medical','Medical Plan 2');
    
    
    CREATE TABLE #PlanEnrollment(
       EnrollmentID        INTEGER  NOT NULL PRIMARY KEY 
      ,EmployeeID          INTEGER  NOT NULL
      ,PlanID              INTEGER  NOT NULL
      ,EnrollmentStartDate DATE   NULL
      ,ErollmentEndDate    DATE  NULL
    );
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (1,1,1,'1/1/2015','3/1/2015');
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (2,1,2,'1/1/2014',NULL);
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (3,2,1,'6/1/2013','5/1/2015');
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (4,3,4,'2/1/2013',NULL);
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (5,4,2,'5/3/2015','7/1/2015');
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (6,1,4,'3/2/2015',NULL);
    INSERT INTO #PlanEnrollment(EnrollmentID,EmployeeID,PlanID,EnrollmentStartDate,ErollmentEndDate) VALUES (8,1,3,'3/2/2015',NULL);
    

答案 3 :(得分:0)

此查询将起作用:

SELECT em.[First Name] as EmployeeFirstName, em.[Last Name] as EmployeeLastName
FROM
(
    SELECT pe.EmployeeID, count(DISTINCT p.PlanType) as DistinctPlanTypeCount
    FROM
        PlanEnrollment pe
        JOIN [Plan] p on pe.PlanID = p.PlanID
    WHERE
        pe.EnrollmentStartDate <= GETDATE() and
        (pe.EnrollmentEndDate is NULL or pe.EnrollmentEndDate > GETDATE())
    GROUP BY pe.EmployeeID
) Q1
JOIN Employee em ON Q1.EmployeeID = em.EmployeeID
WHERE Q1.DistinctPlanTypeCount = (SELECT count(DISTINCT PlanType) FROM [Plan])

内部查询返回

╔════════════╦═══════════════════════╗
║ EmployeeID ║ DistinctPlanTypeCount ║
╠════════════╬═══════════════════════╣
║          1 ║                     2 ║
║          3 ║                     1 ║
╚════════════╩═══════════════════════╝

外部查询按不同的PlanType计数获取Employee列和过滤器。

结果是空集

╔═══════════════════╦══════════════════╗
║ EmployeeFirstName ║ EmployeeLastName ║
╚═══════════════════╩══════════════════╝

答案 4 :(得分:0)

保持简单。
第一个FROM PlanEnrollment过滤所有有医疗计划的员工: WHERE p1.PlanID in (1,4) - 其中一项医疗计划 第一个联接将此结果集过滤到拥有Dental的员工 第二个联接将此结果集过滤到具有Vision

的员工

第三次加入只是获得对员工的引用,因此您可以列出他们的名字。 SELECT e.*

SELECT e.*
FROM PlanEnrollemnt p1
JOIN PlanEnrollment p2 on p1.EmployeeID = p2.EmployeeId and PlanId = 2 --Dental
JOIN PlanEnrollment p3 on p1.EmployeeID = p3.EmployeeId and PlanId = 3 -- Vison
JOIN Employee e = p1.EmployeeId = e.EmployeeId
WHERE p1.PlanID in (1,4) -- one of the medical plans

答案 5 :(得分:0)

我使用Pivot做到了,并且奏效了。见下文。

SELECT EmployeeFirstName
    , EmployeeLastName
FROM 
(
    SELECT E.FirstName AS EmployeeFirstName
       , E.LastName AS EmployeeLastName
       , R.EmployeeID
       , P.PlanType
    FROM PlanEnrollment R INNER JOIN [Plan] P
       ON R.PlanID = P.PlanID INNER JOIN Employee E
          ON R.EmployeeID = E.EmployeeID
    WHERE EnrollmentEndDate IS NULL
       AND R.EnrollmentStartDate <= GETDATE()
) SRC PIVOT (COUNT(EmployeeID) FOR PlanType in ([Medical], [Dental], [Vision])) PIVOTTABLE
WHERE Medical > 0
    AND Dental > 0
    AND Vision > 0;