自我加入,两边都缺少行

时间:2015-08-28 15:00:24

标签: sql sql-server

我有一张桌子,其中包含加入和离开组织的人员。

示例数据Sql Fiddle

| pId |     pName |  Unit | YearIn | YearOut |
|-----|-----------|-------|--------|---------|
|   1 |      Noah | North |   2013 |  (null) |
|   2 |      Liam | North |   2013 |    2014 |
|   3 |     Mason | North |   2013 |    2014 |
|   4 |     Jacob | North |   2000 |    2014 |
|   5 |   William |  West |   2000 |    2013 |
|   6 |     Ethan |  West |   2013 |    2013 |
|   7 |   Michael |  West |   2014 |    2015 |
|   8 | Alexander |  West |   2013 |  (null) |

多年> = 2013年,我希望获得按年份和单位分组的参赛作品和参赛作品数。

期望的输出(我不确定是否更容易或更难包含根本不存在数据的行):

| Year |  Unit |  NumIn | NumOut |
|------|-------|--------|--------|
| 2013 | North |      3 | (null) |
| 2013 |  West |      2 |      2 |
| 2014 | North | (null) |      3 |
| 2014 |  West |      1 | (null) |
| 2015 | North | (null) | (null) |      (optional)
| 2015 |  West | (null) |      1 |

为了让NumIn和NumOut成为一排,我猜需要某种自我加入 我试过

SELECT p1.Year, p1.Unit, p1.NumIn, p2.NumOut FROM 
(
    SELECT YearIn AS Year, Unit, COUNT(pId) AS NumIn
    FROM People
    WHERE YearIn >= 2013
    GROUP BY YearIn, Unit
) p1
LEFT JOIN
(
    SELECT YearOut AS Year, Unit, COUNT(pId) AS NumOut
    FROM People
    WHERE YearOut >= 2013
    GROUP BY YearOut, Unit
) p2 
    ON p1.Year = p2.Year AND p1.Unit = p2.Unit

但当然只能在左侧为我提供数据行。

| Year |  Unit | NumIn | NumOut |
|------|-------|-------|--------|
| 2013 | North |     3 | (null) |
| 2013 |  West |     2 |      2 |
| 2014 |  West |     1 | (null) |

结果将输入到Excel中的数据透视表。所以我“欺骗”并使用简单的UNION查询来获取所有数据:

SELECT YearIn AS Year, Unit, COUNT(pId) AS NumIn, NULL AS NumOut
FROM People
WHERE YearIn >= 2013
GROUP BY YearIn, Unit

UNION ALL

SELECT YearOut AS Year, Unit, NULL AS NumIn, COUNT(pId) AS NumOut
FROM People
WHERE YearOut >= 2013
GROUP BY YearOut, Unit

ORDER BY Year, Unit;

结果:

| Year |  Unit |  NumIn | NumOut |
|------|-------|--------|--------|
| 2013 | North |      3 | (null) |
| 2013 |  West | (null) |      2 |
| 2013 |  West |      2 | (null) |
| 2014 | North | (null) |      3 |
| 2014 |  West |      1 | (null) |
| 2015 |  West | (null) |      1 |

这是数据透视表的基础,但我想知道如何在Sql Server中获得所需的结果。

我正在使用Sql Server 2008 R2,以防万一 谢谢!

2 个答案:

答案 0 :(得分:3)

我认为你想要一个子查询和聚合:

SELECT Year, Unit, SUM(NumIn) as NumIn, SUM(NumOut) as NumOut
FROM (SELECT YearIn AS Year, Unit, COUNT(pId) AS NumIn, NULL AS NumOut
      FROM People
      WHERE YearIn >= 2013
      GROUP BY YearIn, Unit
      UNION ALL
      SELECT YearOut AS Year, Unit, NULL AS NumIn, COUNT(pId) AS NumOut
      FROM People
      WHERE YearOut >= 2013
      GROUP BY YearOut, Unit
     ) yu
GROUP BY Year, Unit;

答案 1 :(得分:2)

这应该有效:

WITH Years(y) AS
(
    SELECT * FROM (VALUES('2013'),('2014'),('2015') ) AS tbl(y)
)
,Units AS 
(
    SELECT DISTINCT Unit FROM People
)
SELECT *
FROM Years CROSS JOIN Units
CROSS APPLY(SELECT (SELECT COUNT(*) FROM People AS inP WHERE inP.Unit=Units.Unit AND Years.y=inP.YearIn) AS NumIn
                  ,(SELECT COUNT(*) FROM People AS outP WHERE outP.Unit=units.Unit AND Years.y=outP.YearOut ) As NumOut
) AS Counts
ORDER BY Years.y,Unit