SQL. Объединение записей из 3 или более таблиц на основе дат - PullRequest
0 голосов
/ 04 июля 2018

Мои таблицы выглядят так (только пример):

table1:

TIME     |data1
1.01.2018|aaa
2.01.2018|bbb

table2:

TIME     |data2
1.01.2018|abcd
2.01.2018|cd

Таблица3:

TIME     |data3
1.01.2018|
2.01.2018|d

Теперь я хотел бы взять данные из таблицы 2 и поместить их в таблицу 1, где отсутствуют записи. Если для этой даты нет записей во всех таблицах, то данные в столбце данных равны NULL. Данные, скопированные в таблицу table1, должны совпадать с датой в таблице table2. и если в таблице 1 нет такой же даты, как в таблице 2, эта дата создается.

Пока я пробовал использовать этот код, но скопированные данные недействительны. Если в некоторых таблицах отсутствует пропущенный день, этот пропущенный день создается в столбце времени, но данные в столбце данных неверны.

    SELECT DISTINCT table1.time,table1.data,table2.time,table2.data,table3.time,table3.data
    FROM table1
    LEFT JOIN table2 ON table1.time=table2.time 
    LEFT JOIN table3 ON table1.time=table3.time 

EDIT Вот как должен выглядеть результат: Например, в таблице 3 не было данных для data3 на эту конкретную дату, поэтому ячейка пуста.

TIME     |data1|data2|data3|
1.01.2018|aaa  |abcd |     |
2.01.2018|bbb  |  cd |   d |

Ответы [ 5 ]

0 голосов
/ 04 июля 2018

SQL ниже является просто альтернативой для вставки отсутствующих дат в Таблицу1.

--
-- insert those into Table1 that are in Table2 but not in Table1
--
insert into Table1 ("time", data1)
select "time", data2
from Table2 as t2
where not exists
(
  select 1
  from Table1 as t1
  where t1."time" = t2."time"
);

--
-- insert those into Table1 that are in Table3 but not in Table1
--
insert into Table1 ("time", data1)
select "time", data3
from Table3 as t3
where not exists
(
  select 1
  from Table1 as t1
  where t1."time" = t3."time"
);

Затем добавьте даты, которые все еще отсутствуют в Таблице1 после всего этого.
Ниже приведен пример для MS SQL Server:

;with RCTE_DATERANGE as 
( 
   select min([time]) as dt, max([time]) as max_dt
   from Table1
   union all 
   select dateadd(day, 1, dt), max_dt 
   from RCTE_DATERANGE where dt < max_dt 
) 
insert into Table1 ([time])
select dt 
from RCTE_DATERANGE AS rcte
where not exists
(
  select 1
  from Table1 as t1
  where t1.[time] = rcte.dt
);

-- Just checking
;with RCTE_DATERANGE as 
( 
   select min([time]) as dt, max([time]) as max_dt
   from Table1
   union all 
   select dateadd(day, 1, dt), max_dt 
   from RCTE_DATERANGE where dt < max_dt 
) 
select rcte.dt, t1.[time] as time1, t2.[time] as time2, t3.[time] as [time3], t1.data1, t2.data2, t3.data3  
from RCTE_DATERANGE AS rcte
full join Table1 t1 on t1.[time] = rcte.dt
full join Table2 t2 on t2.[time] = rcte.dt
full join Table3 t3 on t3.[time] = rcte.dt;
0 голосов
/ 04 июля 2018

Применить простое левое соединение после объединения.

DECLARE @t1 table
(
TIMEDate1 DATE
,Data1 VARCHAR(50)
)

DECLARE @t2 table
(
TIMEDate2 DATE
,Data2 VARCHAR(50)
)

DECLARE @t3 table
(
TIMEDate3 DATE
,Data3 VARCHAR(50)
)


insert @t1 (TIMEDate1,Data1 ) select getdate(),'aaa'
insert @t1 (TIMEDate1,Data1 ) select getdate()+1,'bbb'

insert @t2 (TIMEDate2,Data2 ) select getdate(),'abcd'
insert @t2 (TIMEDate2,Data2 ) select getdate()+1,'cd'

insert @t3 (TIMEDate3,Data3 ) select getdate(),''
 insert @t3 (TIMEDate3,Data3 ) select getdate()+1,'d'

SELECT t.TIMEDate,t1.Data1,t2.Data2,t3.Data3 
FROM (
SELECT distinct TIMEDate1  as  TIMEDate FROM @t1
UNION 
SELECT distinct TIMEDate2 as TIMEDate FROM @t2
UNION 
SELECT distinct TIMEDate3 as TIMEDate FROM @t3
) t
left JOIN @t1 t1 ON t1.TIMEDate1 = t.TIMEDate
left JOIN @t2 t2 ON t2.TIMEDate2 = t.TIMEDate
left JOIN @t3 t3 ON t3.TIMEDate3 = t.TIMEDate
--order by t1.TIMEDate1 asc
0 голосов
/ 04 июля 2018

Начните процесс с

SELECT [DISTINCT] TIME FROM TABLE1
UNION [DISTINCT]
SELECT [DISTINCT] TIME FROM TABLE2
UNION [DISTINCT]
SELECT [DISTINCT] TIME FROM TABLE3

А затем СЛЕДУЕТ ПРИСОЕДИНИТЬСЯ к трем таблицам.

0 голосов
/ 04 июля 2018

Попробуйте это:

with cte as (Select time from table1 union Select time from table2 union Select time from table3)
    SELECT cte.time,table1.data as data1,table2.data as data2,table3.data as data3
    FROM cte
    LEFT JOIN table1 ON table1.time=cte.time 
    LEFT JOIN table2 ON cte.time=table2.time 
    LEFT JOIN table3 ON cte.time=table3.time 
0 голосов
/ 04 июля 2018

Вам нужно полное соединение вместо левого. (вы не указали серверную часть. Здесь пример с MS SQL) т.е.:

SELECT  
coalesce(table1."time",table2."time", table3."time") as "time",
         table1.data1,table2.data2,table3.data3
    FROM table1
    full JOIN table2 ON table1."time"=table2."time" 
    full JOIN table3 ON table1."time"=table3."time" ;

Выход:

Time    data1   data2   data3
1.01.2018   aaa abcd    (null)
2.01.2018   bbb cd      d

РЕДАКТИРОВАТЬ: различные в вашем коде предполагает, что вы хотите только одну строку в день. Тогда не ясно, какое значение столбца следует использовать. Предполагая, что что-нибудь подойдет, вы можете выполнить агрегирование следующим образом:

SELECT  
coalesce(table1."time",table2."time", table3."time") as "time",
         max(table1.data1) as data1,
         max(table2.data2) as data2,
         max(table3.data3) as data3
    FROM table1
    full JOIN table2 ON table1."time"=table2."time" 
    full JOIN table3 ON table1."time"=table3."time" 
  group by coalesce(table1."time",table2."time", table3."time");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...