SQL 两列完全连接
SQL Full join on two columns
我正在尝试连接两个 table,但是 emp_id 和 scheme_id 列可能为空或未填充在任一 table 中,但如果已填充在任一情况下,我都需要 return 每个计划的该员工的总数 pen_ee(下面进一步 table 描述)。我无法编辑 table 结构,必须使用现有的结构。
我一直在尝试使用完全联接来执行此操作,但不明白是否可以对两个字段 emp_id 和 scheme_id 进行完全联接以获得所需的结果。
Table PAYAUDPEN
这是一年的前两个月。
- 员工 A 已将 44.06 捐给计划 BMAL。
- 员工 B 已将 98.06 捐给计划 BMAL。
- 员工 B 已将 98.06 捐给计划 CLFL。
emp_id, period_id, scheme_id, pen_ee
A, 201601, BMAL, 22.03
A, 201602, BMAL, 22.03
B, 201601, BMAL, 98.06
B, 201602, CLFL, 98.06
Table PAYISPEN
这是一年中的第三个月和当前月份。系统总是把当前月份放入这个table)
- 员工 A 给出了 22.03.
- 员工 B 给出了 98.06.
(请注意,员工 B 在第 3 个月没有再次向 BMAL 计划供款,这是问题的一部分)。
emp_id, scheme_id, pen_ee
A, BMAL, 22.03
B, CLFL, 98.06
要求的结果
SQL 声明需要 return 将 3 个时期加在一起,对于每个员工他们贡献的每个计划。
- 对于方案 BMAL,员工 A 为 44.06 + 22.03=66.09。
- 对于方案 BMAL,员工 B 将为 98.06 + NULL =98.06。
- 对于方案 CLFL,员工 B 为 98.06 + 98.06=196.12。
A, BMAL, 66.09
B, BMAL, 98.06
B, CLFL, 196.12
创建两个 table 的基础知识并使用上面的示例数据填充 运行 以下查询。
CREATE TABLE [dbo].[payaudpen](
[emp_id] [char](10) NOT NULL,
[period_id] [char](6) NOT NULL,
[scheme_id] [char](10) NOT NULL,
[pen_ee] [numeric](15, 2) NULL)
CREATE TABLE [dbo].[payispen](
[emp_id] [char](10) NOT NULL,
[scheme_id] [char](10) NOT NULL,
[pen_ee] [numeric](15, 2) NULL )
INSERT INTO payaudpen VALUES ('A','201601','BMAL','22.03'), ('A','201602','BMAL','22.03'), ('B','201601','BMAL','98.06'), ('B','201602','CLFL','98.06')
INSERT INTO payispen VALUES ('A','BMAL','22.03'), ('B','CLFL','98.06')
我正在使用的当前声明:
SELECT a.emp_id,
a.scheme_id,
SUM(a.pen_ee)+AVG(b.pen_ee)
FROM payaudpen a
FULL JOIN payispen b
ON a.emp_id=b.emp_id
GROUP BY a.scheme_id, a.emp_id
结果不正确
return 每个方案的员工 B 的正确值。
A, BMAL, 66.09
B, BMAL, 196.12
B, CLFL, 196.12
您需要在解决方案中更改的关键是使用 ISNULL() 来确保当 table b 有数据但 table a 没有数据时密钥出现。否则,您将得到如下所示的行:
空 |空 | 98.06
我推荐:
SELECT ISNULL(a.emp_id,b.emp_id) AS emp_id
ISNULL(a.scheme_id, b.scheme_id) AS scheme_id
SUM(a.pen_ee)+AVG(b.pen_ee) AS pen_ee
FROM payaudpen a
FULL JOIN payispen b
ON a.emp_id=b.emp_id
AND a.scheme_id=b.scheme_id
WHERE a.emp_id in ('A','B')
and period_id in ('201601','201602')
GROUP BY ISNULL(a.emp_id,b.emp_id), ISNULL(a.scheme_id, b.scheme_id)
显然您只想连接具有相同 emp_id
和 相同 scheme_id
的行。这在外连接中是可能的,就像在内连接中一样。我推断您还想合并两个 table 中的 emp_id
和 scheme_id
列,以便当 a
不提供它们时,它们来自 b
, 反而。这将做到:
SELECT
COALESCE(a.emp_id, b.emp_id) AS emp_id,
COALESCE(a.scheme_id, b.scheme_id) AS scheme_id,
SUM(a.pen_ee)+AVG(b.pen_ee) AS pen_ee
FROM
payaudpen a
FULL JOIN payispen b
ON a.emp_id = b.emp_id AND a.scheme_id = b.scheme_id
WHERE
COALESCE(a.emp_id, b.emp_id) in ('A','B')
AND (a.period_id IS NULL OR a.period_id in ('201601','201602'))
GROUP BY COALESCE(a.scheme_id, b.scheme_id), COALESCE(a.emp_id, b.emp_id)
注意使用COALESCE()
来处理tablea
不提供emp_id
或scheme_id
的情况;使用 SQL 服务器,您也可以使用 ISNULL()
代替它。还要注意 WHERE
条件中 a.period_id IS NULL
的余量——这是必要的(与 COALESCE()
ing 结合)以包含来自 b
行但没有对应的数据a
行。
您正在尝试对两个表求和,使用 union all 使表成为具有更多行的关系,而不是使用 join 使表成为具有更多列的关系:
WITH all_records AS (SELECT emp_id
, scheme_id
, pen_ee
FROM payispen
UNION ALL
SELECT emp_id
, scheme_id
, pen_ee FROM payaudpen)
SELECT emp_id, scheme_id, SUM(pen_ee)
FROM all_records
GROUP BY emp_id, scheme_id
结果:
emp_id scheme_id (No column name)
A BMAL 66.09
B BMAL 98.06
B CLFL 196.12
我正在尝试连接两个 table,但是 emp_id 和 scheme_id 列可能为空或未填充在任一 table 中,但如果已填充在任一情况下,我都需要 return 每个计划的该员工的总数 pen_ee(下面进一步 table 描述)。我无法编辑 table 结构,必须使用现有的结构。
我一直在尝试使用完全联接来执行此操作,但不明白是否可以对两个字段 emp_id 和 scheme_id 进行完全联接以获得所需的结果。
Table PAYAUDPEN
这是一年的前两个月。
- 员工 A 已将 44.06 捐给计划 BMAL。
- 员工 B 已将 98.06 捐给计划 BMAL。
- 员工 B 已将 98.06 捐给计划 CLFL。
emp_id, period_id, scheme_id, pen_ee
A, 201601, BMAL, 22.03
A, 201602, BMAL, 22.03
B, 201601, BMAL, 98.06
B, 201602, CLFL, 98.06
Table PAYISPEN
这是一年中的第三个月和当前月份。系统总是把当前月份放入这个table)
- 员工 A 给出了 22.03.
- 员工 B 给出了 98.06.
(请注意,员工 B 在第 3 个月没有再次向 BMAL 计划供款,这是问题的一部分)。
emp_id, scheme_id, pen_ee
A, BMAL, 22.03
B, CLFL, 98.06
要求的结果
SQL 声明需要 return 将 3 个时期加在一起,对于每个员工他们贡献的每个计划。
- 对于方案 BMAL,员工 A 为 44.06 + 22.03=66.09。
- 对于方案 BMAL,员工 B 将为 98.06 + NULL =98.06。
- 对于方案 CLFL,员工 B 为 98.06 + 98.06=196.12。
A, BMAL, 66.09
B, BMAL, 98.06
B, CLFL, 196.12
创建两个 table 的基础知识并使用上面的示例数据填充 运行 以下查询。
CREATE TABLE [dbo].[payaudpen](
[emp_id] [char](10) NOT NULL,
[period_id] [char](6) NOT NULL,
[scheme_id] [char](10) NOT NULL,
[pen_ee] [numeric](15, 2) NULL)
CREATE TABLE [dbo].[payispen](
[emp_id] [char](10) NOT NULL,
[scheme_id] [char](10) NOT NULL,
[pen_ee] [numeric](15, 2) NULL )
INSERT INTO payaudpen VALUES ('A','201601','BMAL','22.03'), ('A','201602','BMAL','22.03'), ('B','201601','BMAL','98.06'), ('B','201602','CLFL','98.06')
INSERT INTO payispen VALUES ('A','BMAL','22.03'), ('B','CLFL','98.06')
我正在使用的当前声明:
SELECT a.emp_id,
a.scheme_id,
SUM(a.pen_ee)+AVG(b.pen_ee)
FROM payaudpen a
FULL JOIN payispen b
ON a.emp_id=b.emp_id
GROUP BY a.scheme_id, a.emp_id
结果不正确
return 每个方案的员工 B 的正确值。
A, BMAL, 66.09
B, BMAL, 196.12
B, CLFL, 196.12
您需要在解决方案中更改的关键是使用 ISNULL() 来确保当 table b 有数据但 table a 没有数据时密钥出现。否则,您将得到如下所示的行:
空 |空 | 98.06
我推荐:
SELECT ISNULL(a.emp_id,b.emp_id) AS emp_id
ISNULL(a.scheme_id, b.scheme_id) AS scheme_id
SUM(a.pen_ee)+AVG(b.pen_ee) AS pen_ee
FROM payaudpen a
FULL JOIN payispen b
ON a.emp_id=b.emp_id
AND a.scheme_id=b.scheme_id
WHERE a.emp_id in ('A','B')
and period_id in ('201601','201602')
GROUP BY ISNULL(a.emp_id,b.emp_id), ISNULL(a.scheme_id, b.scheme_id)
显然您只想连接具有相同 emp_id
和 相同 scheme_id
的行。这在外连接中是可能的,就像在内连接中一样。我推断您还想合并两个 table 中的 emp_id
和 scheme_id
列,以便当 a
不提供它们时,它们来自 b
, 反而。这将做到:
SELECT
COALESCE(a.emp_id, b.emp_id) AS emp_id,
COALESCE(a.scheme_id, b.scheme_id) AS scheme_id,
SUM(a.pen_ee)+AVG(b.pen_ee) AS pen_ee
FROM
payaudpen a
FULL JOIN payispen b
ON a.emp_id = b.emp_id AND a.scheme_id = b.scheme_id
WHERE
COALESCE(a.emp_id, b.emp_id) in ('A','B')
AND (a.period_id IS NULL OR a.period_id in ('201601','201602'))
GROUP BY COALESCE(a.scheme_id, b.scheme_id), COALESCE(a.emp_id, b.emp_id)
注意使用COALESCE()
来处理tablea
不提供emp_id
或scheme_id
的情况;使用 SQL 服务器,您也可以使用 ISNULL()
代替它。还要注意 WHERE
条件中 a.period_id IS NULL
的余量——这是必要的(与 COALESCE()
ing 结合)以包含来自 b
行但没有对应的数据a
行。
您正在尝试对两个表求和,使用 union all 使表成为具有更多行的关系,而不是使用 join 使表成为具有更多列的关系:
WITH all_records AS (SELECT emp_id
, scheme_id
, pen_ee
FROM payispen
UNION ALL
SELECT emp_id
, scheme_id
, pen_ee FROM payaudpen)
SELECT emp_id, scheme_id, SUM(pen_ee)
FROM all_records
GROUP BY emp_id, scheme_id
结果:
emp_id scheme_id (No column name)
A BMAL 66.09
B BMAL 98.06
B CLFL 196.12