Сопоставление дат с SQL - PullRequest
0 голосов
/ 23 мая 2018

У меня есть две разные таблицы, как показано ниже, и я хотел бы объединить их, используя два столбца Product и Date.Table1 имеет формат даты ГГГГММДД, а Table2 имеет формат ГГГГММ.Здесь в Table2 это последний рабочий день месяца.Есть ли способ объединить эти две таблицы.

Таблица 1:

Product Date    State
A   20080107    NY
A   20080131    TX
B   20100212    CT
B   20100226    MT
C   20150312    HG
C   20140425    UP

Таблица 2:

Product Date    Country
A   200801  USA
C   201503  AUS
B   201002  UK
B   201704  FIN
C   200605  IRE
A   200805  CAN

ВЫХОД:

Product Date    State   Country
A   20080131    TX  USA
B   20100226    MT  UK

Ответы [ 3 ]

0 голосов
/ 23 мая 2018

Согласно OP, date сохраняется как INT.Найдите последнюю дату каждого месяца (FLOOR(date/100)) для каждого продукта в таблице1 и используйте ее для объединения с таблицей2.

select 
t1.product,
t1.date,
t1.state,
t2.country
from 
table2 t2
join
(select table1.* 
 from table1 join
 (select product, max(date) lastdayOfMonth 
  from table1
  group by product, floor(date/100)) t 
  on table1.product = t.product and table1.date = t.lastdayofMonth ) t1 
 on 
 t1.product = t2.product
 and
 t1.date = t2.date 

Демонстрация: sqlfiddle

0 голосов
/ 23 мая 2018

Если я правильно понимаю, вы хотите, чтобы все строки в table1, где table1.date соответствовали последнему рабочему дню месяца в table2.date.

ЯПредположим, что это real date столбцов , несмотря на форматирование.Если это не так, конвертируйте их в реальные даты.table1.date уже находится в приемлемом формате YYYYMMDD, поэтому MySQL преобразует его для вас.table2.date можно изменить на приемлемый формат YYYYMMDD с помощью concat(date, "01").Затем вы можете использовать функции даты MySQL .Я настоятельно рекомендую вам сделать это преобразование постоянным, изменив таблицы, это сделает все проще и быстрее.

У MySQL нет последнего рабочего дня, но у него есть last_dayи dayofweek (и здесь я вздыхаю о несовместимых соглашениях имен функций MySQL).Чтобы получить последний рабочий день, мы находим последний день месяца, затем, какой это день недели, и вычитаем при необходимости.

досадно, dayofweek возвращает 1 для воскресенья, а не 0, что делает вещинемного сложнее.

case
    -- Sunday, move to Friday
    when dayofweek(last_day('2010-02-01')) = 1 then last_day('2010-02-01') - 2
    -- Saturday, move to Friday
    when dayofweek(last_day('2010-02-01')) = 7 then last_day('2010-02-01') - 1
    -- Weekday
    when dayofweek(last_day('2010-02-01')) in(2,3,4,5,6) then last_day('2010-02-01') 
    else null
end as last_business_day;

Это было бы лучше сделать как хранимую процедуру.Это не только позволяет избежать повторения, потому что мы можем использовать переменные, но также инкапсулирует логику в аккуратную, тестируемую функцию.Мы также можем объявить его deterministic, что означает, что MySQL может кэшировать вычисления для тех же дат, экономя некоторое время процессора.

create function last_business_day(date date)
returns date
deterministic
begin
    declare last_day date;
    declare last_dow int;

    set last_day = last_day(date);
    set last_dow = dayofweek(last_day);
    return case
        -- Sunday, move to Friday
        when last_dow = 1 then
            last_day - 2
        -- Saturday, move to Friday
        when last_dow = 7 then
            last_day - 1
        -- Weekday
        when last_dow in(2,3,4,5,6) then
            last_day
        else
            null
    end;
end;

Теперь мы можем задать last_business_day('2010-02-01') и получить 2010-02-26.

Вооружившись этим, запрос становится простым.

select t1.product, t1.date, t1.state, t2.country
from table1 t1
join table2 t2 on t1.product = t2.product and
                  t1.date = last_business_day(t2.date)
0 голосов
/ 23 мая 2018

Вот ваш решенный SQL:

select x.product,x.date,x.state,x.country
from
(select x.product,x.date,x.state,country
from (select product,max(date) date from table1 group by product) t1
join table2 on (left(t1.date,6) = table2.date)
join table1 x on (left(x.date,6) = left(t1.date,6))) x
join (select x.product,max(x.date) date
from (select product,max(date) date from table1 group by product) t1
join table2 on (left(t1.date,6) = table2.date)
join table1 x on (left(x.date,6) = left(t1.date,6))
     group by x.product) y
on (x.product = y.product and x.date = y.date);

Пример:

mysql> create table table1(product varchar(20),date varchar(8), state varchar(20));
Query OK, 0 rows affected (0.41 sec)

mysql> insert into table1 values
    -> ('A','20080107','NY'),
    -> ('A','20080131','TX'),
    -> ('B','20100212','CT'),
    -> ('B','20100226','MT'),
    -> ('C','20150312','HG'),
    -> ('C','20140425','UP');
Query OK, 6 rows affected (0.13 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> 
mysql> create table table2(Product varchar(20),Date varchar(8),Country varchar(20));
Query OK, 0 rows affected (0.33 sec)

mysql> insert into table2 values
    -> ('A','200801','USA'),
    -> ('C','201503','AUS'),
    -> ('B','201002','UK'),
    -> ('B','201704','FIN'),
    -> ('C','200605','IRE'),
    -> ('A','200805','CAN');
Query OK, 6 rows affected (0.13 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select x.product,x.date,x.state,x.country
    -> from
    -> (select x.product,x.date,x.state,country
    -> from (select product,max(date) date from table1 group by product) t1
    -> join table2 on (left(t1.date,6) = table2.date)
    -> join table1 x on (left(x.date,6) = left(t1.date,6))) x
    -> join (select x.product,max(x.date) date
    -> from (select product,max(date) date from table1 group by product) t1
    -> join table2 on (left(t1.date,6) = table2.date)
    -> join table1 x on (left(x.date,6) = left(t1.date,6))
    ->      group by x.product) y
    -> on (x.product = y.product and x.date = y.date);
+---------+----------+-------+---------+
| product | date     | state | country |
+---------+----------+-------+---------+
| A       | 20080131 | TX    | USA     |
| B       | 20100226 | MT    | UK      |
| C       | 20150312 | HG    | AUS     |
+---------+----------+-------+---------+
3 rows in set (0.01 sec)

Демо

http://www.sqlfiddle.com/#!9/6ef0e5/11

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...