Объединение данных из нескольких строк в одну - PullRequest
2 голосов
/ 03 марта 2020

Первый вопрос здесь, поэтому я постараюсь сделать все возможное, чтобы уточнить.

У меня есть 2 таблицы:

  1. "TABLE1", которая содержит запись для каждого биржевого кода и список атрибутов. В ТАБЛИЦЕ 1 есть только одна запись для каждого stock_code
  2. "TABLE2", которая содержит журнал изменений атрибутов продуктов со временем.

"TABLE2" содержит следующие поля :.

  1. stock_code
  2. stock_attribute
  3. old_value
  4. new_value
  5. change_date
  6. change_time

В ТАБЛИЦЕ 2 есть несколько записей ofr для каждого stock_ кода.

Каждый раз, когда изменяется товарная позиция, в Таблице 2 делается другая запись с измененным атрибутом, датой изменения, временем, старым значение и новое значение.

Я хочу создать запрос, в результате которого будет таблица, содержащая одну запись для каждого кода акции (из ТАБЛИЦЫ 1), и столбец для каждой недели за прошедший год со значением в каждое поле является последним записанным «new_val» за эту неделю (из таблицы 2)

я пробовал

SELECT a.`stcode`, b.`week1`, b.`week2`, b.`week3`, b.`week4` etc. etc.
 from (SELECT stcode, )as a
 LEFT JOIN (SELECT stcode, 
(CASE WHEN chngdate BETWEEN DATE_SUB(CURDATE(),INTERVAL 363 DAY)  AND DATE_SUB(CURDATE(),INTERVAL 357 DAY)  THEN newval END)week1,
(CASE WHEN chngdate BETWEEN DATE_SUB(CURDATE(),INTERVAL 356 DAY)  AND DATE_SUB(CURDATE(),INTERVAL 350 DAY)  THEN newval END)week2,
(CASE WHEN chngdate BETWEEN DATE_SUB(CURDATE(),INTERVAL 349 DAY)  AND DATE_SUB(CURDATE(),INTERVAL 343 DAY)  THEN newval END)week3,
(CASE WHEN chngdate BETWEEN DATE_SUB(CURDATE(),INTERVAL 342 DAY)  AND DATE_SUB(CURDATE(),INTERVAL 336 DAY)  THEN newval END)week4,
(etc
etc
etc


    FROM (SELECT * from TABLE 2  ORDER BY "chngdate" DESC, "chngtime" DESC )as sub) as b ON b.stcode = s.stcode
ORDER BY stcode ASC

Проблема в том, что я получаю несколько строк для кода stock_, который имеет Mutliple записи .... например e, для stock_code abc123 я получаю результат

STCODE       WEEK1     WEEK2     WEEK3      WEEK4      WEEK5     WEEK6
abc123        null      null       4         null      null       null
abc123        2         null       null      null      null       null
abc123        null      null       null      null      3          null

, что я ХОЧУ это:

STCODE       WEEK1     WEEK2     WEEK3      WEEK4      WEEK5     WEEK6
abc123        2         null       4         null      3        null

Я также пробовал следующее, но запрос занял так много времени, он никогда закончено (было 52 производных таблицы!)

SELECT a.`stcode`, w1.`new_value`, w2.`new_value`, w3.`new_value`, w4.`new_value` etc. etc.
 from (SELECT stcode, )as a
 LEFT JOIN (SELECT stcode, 
LEFT JOIN (SELECT stcode, depot, fieldname, chngdate, chngtime, newval from STDepotAmendmentsLog WHERE chngdate BETWEEN DATE_SUB(CURDATE(),INTERVAL 363 DAY)  AND DATE_SUB(CURDATE(),INTERVAL 357 DAY)  ORDER BY "chngdate" DESC, "chngtime" DESC)as w1 on s.stcode = w1.stcode
etc for week 2, 3, 4 etc etc

1 Ответ

1 голос
/ 03 марта 2020

Вы можете сделать следующее:

  1. Найти наибольшую дату для каждой "недели"
  2. Найти строки, соответствующие этим датам
  3. Использовать условное агрегирование для преобразовать строки в столбцы

Вот примерный план кода. Предполагается, что, например, если сегодня 2020-03-03, то неделя 52 - с 2020-02-26 по 2020-03-03. Отрегулируйте при необходимости:

SELECT t.stock_code
     , MAX(CASE WHEN weeknum = 51 THEN new_value END) AS week01
     , MAX(CASE WHEN weeknum = 50 THEN new_value END) AS week02
     , MAX(CASE WHEN weeknum =  1 THEN new_value END) AS week51
     , MAX(CASE WHEN weeknum =  0 THEN new_value END) AS week52
FROM table2 AS t
JOIN (
    SELECT stock_code
         , DATEDIFF(CURRENT_DATE, change_date) div 7 AS weeknum -- count multiples of 7
         , MAX(change_date) AS greatest_date
    GROUP BY stock_code, weeknum
    FROM table2
)  AS a ON t.stock_code = a.stock_code AND t.change_date = a.greatest_date
GROUP BY t.stock_code
...