如何在 SQL 中加入六个表,同时只包含某些行?

Posted

技术标签:

【中文标题】如何在 SQL 中加入六个表,同时只包含某些行?【英文标题】:How do I join six tables in SQL while only including certain rows? 【发布时间】:2018-01-20 01:41:10 【问题描述】:

我有 6 个人员表,对应 6 个日历年的数据,2010-2015。每个表中的每一行都有一个唯一的变量 id,对应于全年参与的个人,每个表都有变量年份,该年份设置为参与年份。

如果个人全年没有参与,则该表中没有相应的行。

例如,

2010 年

id year (other variables)

0000001 2010 .

0000002 2010 .

000003 2010 .

0000004 2010 .

2011 年

id year (other variables)

0000002 2011 .

0000003 2011 .

0000004 2011 .

0000005 2011 .

2012 年

id year (other variables)

0000001 2012 .

0000002 2012 .

0000003 2012 .

0000005 2012 .

id 1 的情况下,他们没有参加 2011 年全年,但确实在 2012 年回来,id 4 于 2012 年离开,id 5 于 2011 年加入。

我想将所有这些表连接在一起,并获取至少连续 2 年出现的行(例如,对于 id 1,它们不会在此连接表中),并创建一个对应于的新变量一个人在数据集中的年数以及该人开始的时间。

merged-table
id startyear enrolledyears (other variables)
0000002 2010      3             .
0000003 2010      3             .
0000004 2010      2             .
0000005 2011      2             .

到目前为止,我能够将其概念化为一系列左连接,这样每个表中的 year 变量就成为 startyear 变量,但我认为当有人输入不是 2010 年时,这个过程就会崩溃。

非常感谢任何建议!

【问题讨论】:

【参考方案1】:

首先,将事物拆分为按年命名的表格并不是一个好的表格设计。你应该把所有东西都放在同一张桌子上。现在,您添加的每一年都需要添加到您提出的任何 SQL 中。

你可以让它看起来像一张这样的桌子:

SELECT ID, Year FROM entear2010 
  UNION ALL
SELECT ID, Year FROM entear2011 
  UNION ALL
SELECT ID, Year FROM entear2012

现在您可以使用该构造来获得您想要的东西。你把它放到一个叫做 CTE 的东西中:

WITH AllData AS (
SELECT ID, Year FROM entear2010 
  UNION ALL
SELECT ID, Year FROM entear2011 
  UNION ALL
SELECT ID, Year FROM entear2012
)

SELECT * FROM AllData

现在您可以“自行加入”来检查一个 id 是否在前一年:

WITH AllData AS (
SELECT ID, Year FROM entear2010 
  UNION ALL
SELECT ID, Year FROM entear2011 
  UNION ALL
SELECT ID, Year FROM entear2012
)
SELECT Current.ID, Current.Year 
FROM AllData As Current
INNER JOIN AllData As Prior
ON  Current.ID = Prior.ID
AND Current.Year-1 = Prior.Year

这将为您提供连续两年的人员名单。现在你简单总结一下:

WITH AllData AS (
SELECT ID, Year FROM entear2010 
  UNION ALL
SELECT ID, Year FROM entear2011 
  UNION ALL
SELECT ID, Year FROM entear2012
)

SELECT ID, COUNT(*) YearsEnrolled, MIN(Year) As StartYear
FROM AllData
WHERE ID IN (
  SELECT DISTINCT Current.ID
  FROM AllData As Current
  INNER JOIN AllData As Prior
  ON  Current.ID = Prior.ID
  AND Current.Year-1 = Prior.Year
  )
GROUP BY ID

我想这就是你所追求的。

可能有一种更聪明的方法可以使用窗口函数来实现它......但其他人无疑会发布它。

【讨论】:

【参考方案2】:

你必须先合并所有表(通过联合全部或创建临时表),然后在 SQL 下运行:

select * from (
select MEMBER_ID, max(YEAR_NUM) MAX_YEAR, MIN(YEAR_NUM) MIN_YEAR, COUNT(YEAR_NUM) YEAR_COUNT
from merged_tables
group by MEMBER_ID) w1
where MAX_YEAR=MIN_YEAR+YEAR_COUNT-1 and YEAR_COUNT>1

以上 SQL 将返回所有连续注册年数大于一年的成员 ID。

【讨论】:

以上是关于如何在 SQL 中加入六个表,同时只包含某些行?的主要内容,如果未能解决你的问题,请参考以下文章

在 like 语句中加入 SQL Server 表

SQL 选择 - 某些行不会显示

如何找到 SQL 查询失败的确切行

当某些行包含逗号作为千位分隔符和“标志并且没有小数的行没有标志时如何在R中读取数据

如何在具有某些首字母的新表中插入所有行(pl/sql)

如何为复杂的 sql 查询获取中间数据。 PostgreSQL