2015-09-22 7 views
2

Я пытаюсь присоединиться к двум таблицам, но столбцы emp_id и schem_id могут быть пустыми или не заполнены ни в одной из таблиц, но если они заполнены, то мне нужно вернуть общее pen_ee для этого сотрудника для каждой схемы (далее описание ниже). Я не могу редактировать структуру таблицы и работать с тем, что у меня есть.SQL Полное соединение на двух столбцах

Я пытался использовать полное соединение для этого, но не понимаю, можете ли вы выполнить полное соединение на двух полях emp_id & schem_id, чтобы получить требуемый результат.

Таблица PAYAUDPEN
Это первые два месяца года.
- Сотрудник А дал 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 

Таблица PAYISPEN
Это третий & текущий месяц года. Система всегда помещает текущий месяц в эту таблицу)
- Сотрудник А дал 22.03.
- Сотрудник B дал 98.06.
(Примечание сотрудника B больше не вносит вклад в схему BMAL в месяце 3, что является частью проблемы).

emp_id, scheme_id, pen_ee 
A, BMAL, 22.03 
B, CLFL, 98.06 

Требуемый результат SQL-оператор должен вернуть 3 периода суммируются, для каждого сотрудника для каждой схемы, что они способствовали.
- Сотрудник А будет 44,06 + 22,03 = 66,09 для схемы BMAL.
- Сотрудник B будет 98,06 + NULL = 98,06 для схемы BMAL.
- Сотрудник B будет 98,06 + 98,06 = 196,12 для схемы CLFL.

A, BMAL, 66.09 
B, BMAL, 98.06 
B, CLFL, 196.12 

Для создания основы двух таблиц и заполнения в примере выше данные запустить следующие запросы.

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 

Неправильный результат
Не возвращает правильное значение для сотрудников B для каждой схемы.

A, BMAL, 66.09 
B, BMAL, 196.12 
B, CLFL, 196.12 
+3

Значение «C» загадочно появляется в желаемых результатах, но не находится ни в одном из входных столбцов. –

+1

Я читал вопрос и думал то же самое! Откуда это взялось? значение «C» –

+0

Я думаю, что OP означало «...» в конце примерных таблиц. –

ответ

1

Вы пытаетесь подвести через две таблицы, использование союза все, чтобы сделать таблицы в одном отношении с большим количеством строк, вместо того, чтобы присоединиться, чтобы сделать таблицы в связи с большим количеством столбцов:

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 
+0

Я не знаком с операторами WITH, но я тестировал его на больших таблицах данных, которые у меня есть. похоже, работает! Благодарю. – CantGetItToWork

0

Ключ, что вам нужно изменить в вашем решении является использование ISNULL(), чтобы убедиться, что ключ появляется, когда таблица б имеет данные, но не таблица а. В противном случае вы получите строки, которые выглядят так:

NULL | NULL | 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) 
+0

Я попробовал предложенное решение выше, но это кажется не совсем правильным. Возвращаемый результат: A, BMAL, 66.09, B, BMAL, 196.12, B, CLFL, 196.12 – CantGetItToWork

+0

Я внес изменения в предложение ON. Он работает сейчас? –

+0

Не повезло, я добавил намного больше подробностей к своему первоначальному сообщению, если вы хотите посмотреть еще раз. Возвращаемый результат на этот раз был A, BMAL, 66.09, B, BMAL, NULL, B, CLFL, 196.12. – CantGetItToWork

1

Видимо, вы хотите присоединиться только те строки, которые имеют как один и тот же emp_idи то же scheme_id. Это возможно во внешних соединениях, как и во внутренних соединениях. Я полагаю, что вы также хотите объединить столбцы 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() обрабатывать случаи, когда таблица a не обеспечивает emp_id или scheme_id; с SQL Server вы также можете использовать ISNULL(). Обратите также внимание на учет a.period_id IS NULL в условии WHERE - это необходимо (в сочетании с COALESCE()) включить данные из строк b, которые не имеют соответствующих строк a.

+0

@ConradFrix, нет, это будет иметь другое значение. Строки таблицы 'a', не удовлетворяющие условию, все равно будут включены в результат (потому что это (полное) * внешнее * соединение); они просто не будут соединены ни с какими строками 'b'. –

+0

@JohnBollinger Привет, Джон попробовал это заявление и получил A, BMAL, 66.09, B, BMAL, NULL, C, CLFL, 196.12. Я пытаюсь получить A, BMAL, 66.09, B, BMAL, 98.06, C, CLFL, 98.06 – CantGetItToWork