Pergunta

Digamos que preciso consultar os associados de uma corporação. Eu tenho uma tabela, "transações", que contém dados em todas as transações feitas.

CREATE TABLE `transactions` (
  `transactionID` int(11) unsigned NOT NULL,
  `orderID` int(11) unsigned NOT NULL,
  `customerID` int(11) unsigned NOT NULL,
  `employeeID` int(11) unsigned NOT NULL, 
  `corporationID` int(11) unsigned NOT NULL,
  PRIMARY KEY (`transactionID`),
  KEY `orderID` (`orderID`),
  KEY `customerID` (`customerID`),
  KEY `employeeID` (`employeeID`),
  KEY `corporationID` (`corporationID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

É bastante simples consultar esta tabela para associados, mas há uma reviravolta: um registro de transação é registrado uma vez por funcionário e, portanto, pode haver vários registros para uma corporação por pedido.

Por exemplo, se os funcionários A e B da Corporação 1 estivessem envolvidos na venda de um aspirador de pó para a Corporação 2, haveria dois registros na tabela "Transações"; um para cada funcionário e ambos para a corporação 1. Isso não deve afetar os resultados. Um comércio da Corporação 1, independentemente de quantos de seus funcionários esteve envolvido, deve ser tratado como um.

Fácil, pensei. Vou apenas fazer uma junção em uma mesa derivada, como assim:

SELECT corporationID FROM transactions JOIN (SELECT DISTINCT orderID FROM transactions WHERE corporationID = 1) AS foo USING (orderID)

A consulta retorna uma lista de empresas envolvidas em negociações com a Corporação 1. É exatamente isso que eu preciso, mas é muito lento porque o MySQL não pode usar o índice corporativo para determinar a tabela derivada. Entendo que esse é o caso de todas as subconsminações/tabelas derivadas no MySQL.

Também tentei consultar uma coleção de OrderIds separadamente e usar uma cláusula ridiculamente grande em () (tificamente 100.000 IDs), mas como se vê, MySQL tem problemas usando índices em cláusulas ridiculamente grandes () Um resultado que o tempo de consulta não melhora.

Existem outras opções disponíveis ou esgotei as duas?

Foi útil?

Solução

Se eu entender sua exigência, você pode tentar isso.

select distinct t1.corporationID
from transactions t1
where exists (
    select 1
    from transactions t2
    where t2.corporationID =  1
    and t2.orderID = t1.orderID)
and t1.corporationID != 1;

ou isto:

select distinct t1.corporationID
from transactions t1
join transactions t2
on t2.orderID = t1.orderID
and t1.transactionID != t2.transactionID
where t2.corporationID = 1
and t1.corporationID != 1;

Outras dicas

Seus dados não fazem sentido para mim, acho que você está usando o CorporationId, onde você quer dizer ID do cliente em algum momento, pois sua consulta se junta à tabela de transações à tabela de transações para corporationId = 1 com base no OrderId para obter os corporativos ... Qual seria então 1, certo?

Você pode especificar o que significam o cliente, o Funcionário e as corporações? Como sei que os funcionários A e B são da Corporação 1 - nesse caso, a corporação 1 é a corporação e a corporação 2 é o cliente e é armazenada no cliente?

Se for esse o caso, você só precisa fazer um grupo por:

SELECT customerID
FROM transactions
WHERE corporationID = 1
GROUP BY customerID

(Ou selecione e agrupe o OrderId se você deseja uma linha por pedido em vez de uma linha por cliente.)

Ao usar o grupo, você ignora o fato de que existem vários registros que são duplicados, exceto para o funcionário.

Por outro lado, para devolver todas as empresas que foram vendidas à Corporation 2.

SELECT corporationID
FROM transactions
WHERE customerID = 2
GROUP BY corporationID
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top