Pergunta

Eu olhei por toda parte e ainda não encontrei uma maneira inteligente de lidar com isso, embora tenha certeza de que é possível:

Uma tabela de dados históricos possui informações trimestrais:

CREATE TABLE Quarterly (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
PRIMARY KEY (unique_ID));

Outra tabela de dados históricos (que é muito grande) contém informações diárias:

CREATE TABLE Daily (
unique_ID INT UNSIGNED NOT NULL,
date_posted DATE NOT NULL,
datasource TINYINT UNSIGNED NOT NULL,
data FLOAT NOT NULL,
qtr_ID INT UNSIGNED,
PRIMARY KEY (unique_ID));

O campo QTR_ID não faz parte da alimentação dos dados diários que preencheram o banco de dados - em vez disso, preciso preencher retroativamente o campo QTR_ID na tabela diária com o trimestralmente.unique_id linha ID, usando o que teria sido os dados trimestrais mais recentes sobre Isso diariamente.date_posted para essa fonte de dados.

Por exemplo, se os dados trimestrais forem

101 2009-03-31 1 4.5
102 2009-06-30 1 4.4
103 2009-03-31 2 7.6
104 2009-06-30 2 7.7
105 2009-09-30 1 4.7

e os dados diários são

1001 2009-07-14 1 3.5 ??
1002 2009-07-15 1 3.4 &&
1003 2009-07-14 2 2.3 ^^

Então gostaríamos do? O campo QTR_ID a ser atribuído '102' como o trimestre mais recente para essa fonte de dados nessa data, e && também seria '102' e ^^ seria '104'.

Os desafios incluem que ambas as tabelas (particularmente a tabela diária) são realmente muito grandes, elas não podem ser normalizadas para se livrar das datas repetitivas ou otimizadas de outra forma e, para certas entradas diárias, não há entrada trimestral anterior.

Eu tentei uma variedade de junções, usando o datediff (onde o desafio é encontrar o valor mínimo do datediff maior que o zero) e outras tentativas, mas nada está funcionando para mim - geralmente minha sintaxe está quebrando em algum lugar. Quaisquer idéias são bem -vindas - vou executar quaisquer idéias ou conceitos básicos e relatar de volta.

Foi útil?

Solução

Basta subconsciar o trimestre ID usando algo como:

(
 SELECT unique_ID 
 FROM Quarterly 
 WHERE 
     datasource = ? 
     AND date_posted >= ? 
 ORDER BY
     unique_ID ASC
 LIMIT 1
)

Obviamente, isso provavelmente não lhe dará o melhor desempenho e pressupõe que as datas sejam adicionadas a sequencialmente trimestralmente (caso contrário order by date_posted). No entanto, deve resolver seu problema.

Você usaria esta subconsulta em seu INSERT ou UPDATE declarações como o valor do seu qtr_ID campo para o seu Daily tabela.

Outras dicas

O seguinte parece funcionar exatamente como pretendido, mas certamente é feio (com três chamadas para o mesmo datediff !!), talvez vendo uma consulta de trabalho que alguém possa reduzi -lo ou melhorá -lo:

UPDATE Daily SET qtr_ID = (select unique_ID from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) = 
(SELECT MIN(DATEDIFF(Daily.date_posted, Quarterly.date_posted)) from Quarterly
WHERE Quarterly.datasource = Daily.datasource AND
DATEDIFF(Daily.date_posted, Quarterly.date_posted) > 0));

Depois de mais trabalho nessa consulta, acabei com enormes melhorias de desempenho em relação ao conceito original. A melhoria mais importante foi criar índices nas tabelas diárias e trimestrais - diariamente, criei índices (DataSource, date_posted) e (date_posted, DataSource) usando o Btree e ON (DataSource) usando hash e, trimestralmente, fiz o mesmo coisa. Isso é um exagero, mas garantiu que eu tivesse a opção de que o mecanismo de consulta pudesse usar. Isso reduziu o tempo de consulta para menos de 1% do que tinha sido. (!!)

Em seguida, aprendi que, dadas minhas circunstâncias específicas, eu poderia usar max () em vez de ordenar e limitar, por isso uso uma chamada para max () para obter o apropriado exclusivo_id. Isso reduziu o tempo de consulta em cerca de 20%.

Finalmente, aprendi que, com o mecanismo de armazenamento Innodb, eu poderia segmentar o pedaço da tabela diária que estava atualizando com qualquer consulta, o que me permitiu multi-lida nas consultas com um pouco de gravação e scripts. O processamento paralelo funcionou bem e cada thread reduziu o tempo de consulta linearmente.

Portanto, a consulta básica que está realizando literalmente 1000 vezes melhor do que minha primeira tentativa é:

UPDATE Daily
SET qtr_ID =
(
  SELECT MAX(unique_ID)
  FROM Quarterly
  WHERE Daily.datasource = Quarterly.datasource AND
        Daily.date_posted > Quarterly.dateposted
)
WHERE unique_ID > ScriptVarLowerBound AND
      unique_ID <= ScriptVarHigherBound
;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top