2015-11-10 5 views
7

Sto tentando di unirmi a una società e ai relativi dettagli, nonché alle transazioni anche se non esistono.Il join sinistro non funziona quando seleziono il conteggio da un'altra tabella

Sto contando le transazioni per capire quanti utenti stanno andando a un corso, se non ci sono transazioni voglio ancora unirmi all'azienda e dettagli, ma il conteggio sarebbe 0, nella mia query sotto la tabella training_company è in corso selezionata, ma le training_details non vengono selezionati per qualche motivo:

SELECT training.*, count(distinct training_transactions.training_transaction_course) as completed_training_payments 
FROM training 
LEFT JOIN training_company 
    ON training.course_main = training_company_id 
LEFT JOIN training_details 
    ON training.course_main = training_details_company 
LEFT JOIN training_transactions 
    ON training.course_user = training_transactions.training_transaction_user 
WHERE course_id = ? 
     AND  training_transactions.training_transaction_status = 'complete' 
     AND  training_transactions.training_transaction_payment_status = 'complete' 
     AND course_enabled = 'enabled' 

training_company:

CREATE TABLE IF NOT EXISTS `training_company` (
    `training_company_id` int(11) NOT NULL, 
    `training_company_name` varchar(100) NOT NULL, 
    `training_company_user` int(11) NOT NULL, 
    `training_company_enabled` varchar(50) NOT NULL DEFAULT 'enabled', 
    `training_company_has_avatar` int(5) NOT NULL DEFAULT '0', 
    `training_company_has_banner` int(5) NOT NULL DEFAULT '0' 
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1; 

-- 
-- Dumping data for table `training_company` 
-- 

INSERT INTO `training_company` (`training_company_id`, `training_company_name`, `training_company_user`, `training_company_enabled`, `training_company_has_avatar`, `training_company_has_banner`) VALUES 
(1, '123', 1, 'enabled', 0, 0), 

training_details:

CREATE TABLE IF NOT EXISTS `training_details` (
    `training_details_id` int(11) NOT NULL, 
    `training_details_user` int(11) NOT NULL, 
    `training_details_company` int(11) NOT NULL, 
    `training_details_registration_number` varchar(10) NOT NULL, 
    `training_details_type` varchar(100) NOT NULL, 
    `training_details_name` varchar(100) NOT NULL, 
    `training_details_street` varchar(100) NOT NULL, 
    `training_details_town` varchar(100) NOT NULL, 
    `training_details_county` varchar(100) NOT NULL, 
    `training_details_postcode` varchar(100) NOT NULL, 
    `training_details_country` varchar(100) NOT NULL, 
    `training_details_company_name` varchar(100) NOT NULL, 
    `training_details_company_street` varchar(100) NOT NULL, 
    `training_details_company_town` varchar(100) NOT NULL, 
    `training_details_company_county` varchar(100) NOT NULL, 
    `training_details_company_postcode` varchar(100) NOT NULL, 
    `training_details_company_country` varchar(100) NOT NULL, 
    `training_details_total_employees` varchar(100) NOT NULL, 
    `training_details_fax` varchar(100) NOT NULL, 
    `training_details_landline` varchar(100) NOT NULL, 
    `training_details_mobile` varchar(50) NOT NULL, 
    `training_details_email` varchar(50) NOT NULL, 
    `training_details_website` varchar(250) NOT NULL, 
    `company_differs_address` int(11) NOT NULL DEFAULT '0' 
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1; 

-- 
-- Dumping data for table `training_details` 
-- 

INSERT INTO `training_details` (`training_details_id`, `training_details_user`, `training_details_company`, `training_details_registration_number`, `training_details_type`, `training_details_name`, `training_details_street`, `training_details_town`, `training_details_county`, `training_details_postcode`, `training_details_country`, `training_details_company_name`, `training_details_company_street`, `training_details_company_town`, `training_details_company_county`, `training_details_company_postcode`, `training_details_company_country`, `training_details_total_employees`, `training_details_fax`, `training_details_landline`, `training_details_mobile`, `training_details_email`, `training_details_website`, `company_differs_address`) VALUES 
(1, 0, 1, '0', '', '123', '123', '123', '123456', 'WN8', 'Australia', '123', '123', '123', '', 'WN8', 'Australia', '', '', '', '', '', '', 4), 

formazione:

CREATE TABLE IF NOT EXISTS `training` (
    `course_id` int(11) NOT NULL, 
    `course_user` int(11) NOT NULL, 
    `course_main` int(11) NOT NULL, 
    `course_type` varchar(255) NOT NULL, 
    `course_name` varchar(255) NOT NULL, 
    `course_description` text NOT NULL, 
    `course_location` varchar(255) NOT NULL, 
    `course_duration` varchar(255) NOT NULL, 
    `course_fitness_type` varchar(255) NOT NULL, 
    `course_instructor_name` varchar(255) NOT NULL, 
    `course_price` int(15) NOT NULL, 
    `course_start_date` date NOT NULL, 
    `course_max_attendees` int(8) NOT NULL, 
    `course_accommodation` varchar(255) NOT NULL, 
    `course_accommodation_price` varchar(255) NOT NULL, 
    `course_status` varchar(50) NOT NULL, 
    `course_enabled` varchar(10) NOT NULL DEFAULT 'enabled', 
    `course_location_name` varchar(255) NOT NULL, 
    `course_location_street` varchar(255) NOT NULL, 
    `course_location_town` varchar(255) NOT NULL, 
    `course_location_county` varchar(255) NOT NULL, 
    `course_location_postcode` varchar(255) NOT NULL, 
    `course_location_country` varchar(255) NOT NULL, 
    `course_certificate` varchar(250) NOT NULL, 
    `course_certificate_valid` int(30) NOT NULL 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; 

-- 
-- Dumping data for table `training` 
-- 

INSERT INTO `training` (`course_id`, `course_user`, `course_main`, `course_type`, `course_name`, `course_description`, `course_location`, `course_duration`, `course_fitness_type`, `course_instructor_name`, `course_price`, `course_start_date`, `course_max_attendees`, `course_accommodation`, `course_accommodation_price`, `course_status`, `course_enabled`, `course_location_name`, `course_location_street`, `course_location_town`, `course_location_county`, `course_location_postcode`, `course_location_country`, `course_certificate`, `course_certificate_valid`) VALUES 
(1, 3, 1, 'Hazardous', '123', 'dddddddddddddd', 'other', '14', 'lol', 'lol', 123, '2015-11-09', 4, '0', '', 'pending', 'enabled', '123', '123', '123', '123456', '123', 'Australia', '123', 2), 

Così come posso ottenere il mio iscriverti per lavorare sui dettagli, perché al momento non sta unendo anche se tutto corrisponde

+14

Il 'left join' funziona correttamente. È necessario spostare le condizioni dalle clausole 'where' alle clausole' on'. Francamente, trovo davvero molto difficile seguire le query che combinano 'left join' e' right join', ma dovresti capire la query in modo che tu possa essere in grado di capire quali condizioni vanno dove. –

+0

La tua prosa suggerisce di volere un diritto di partecipazione alla società, non alla sinistra. –

+0

Ho provato ad aggiungerlo a on senza look ea destra join :( –

risposta

5

Come suggerito da Gordon Linoff nel primo commento, spostare le condizioni relative allo training_transactions dalla clausola WHERE allo LEFT JOIN.

Ovviamente, è necessario elencare le colonne in modo esplicito anziché * e aggiungere uno GROUP BY corrispondente per il COUNT per il funzionamento.

SELECT 
    training.course_id 
    ,training.course_user 
    ... 
    ,count(distinct training_transactions.training_transaction_course) as completed_training_payments 
FROM 
    training 
    LEFT JOIN training_company ON training.course_main = training_company_id 
    LEFT JOIN training_details ON training.course_main = training_details_company 
    LEFT JOIN training_transactions 
     ON training_transactions.training_transaction_user = training.course_user 
     AND training_transactions.training_transaction_status = 'complete' 
     AND training_transactions.training_transaction_payment_status = 'complete' 
WHERE 
    training.course_id = ? 
    AND training.course_enabled = 'enabled' 
GROUP BY 
    training.course_id 
    ,training.course_user 
    ... 

Ci sono anche alcune cose a cui dovresti prestare attenzione in questa query.

WHERE 
    course_id = ? 
    AND course_enabled = 'enabled' 

Non è chiaro per una nuova persona che legge la query (come tutti la lettura di questa domanda e la prossima persona che sarà mantenere il vostro codice, che potrebbe essere voi in due anni di tempo) che tabella questi campi appartengono a . Cerca sempre di indicare la tabella esplicitamente, in questo modo:

WHERE 
    training.course_id = ? 
    AND training.course_enabled = 'enabled' 

Aiuta anche a usare gli alias.

In modo simile, non è chiaro che cosa sta succedendo nella JOIN:

LEFT JOIN training_company ON training.course_main = training_company_id 
    LEFT JOIN training_details ON training.course_main = training_details_company 

è solo una svista quando semplificare la query per questa domanda, o questo è il tuo vero codice? In ogni caso, includi il nome della tabella (o alias).

LEFT JOIN training_company ON training.course_main = training_company.training_company_id 
LEFT JOIN training_details ON training.course_main = training_details.training_details_company 
1

io vi suggerisco di andare un percorso diverso del tutto e non usare i join a sinistra. Dato che vuoi tutti i dati dalla tabella di allenamento e vuoi un aggregato (conta nel tuo caso) da una tabella diversa, ti suggerisco di suddividere l'aggregato in una sottoquery separata. Ecco quello che voglio dire (nota ho aggiunto alias per le tabelle di semplificare le cose così):

SELECT t.*, 
     (SELECT count(distinct tt.training_transaction_course) 
      FROM training_company tc   
      JOIN training_details td ON td.course_main = tc.training_details_company 
      JOIN training_transactions tt ON t.course_user = tt.training_transaction_user 
     WHERE t.course_main = tc.training_company_id 
      AND tt.training_transaction_status = 'complete' 
      AND tt.training_transaction_payment_status = 'complete') 
     as completed_training_payments 
FROM training t 
WHERE t.course_id = ? 
    AND t.course_enabled = 'enabled' 

Ciò garantirà una riga restituita per ogni riga della tabella di formazione che corrisponde al course_id inserito. Inoltre, se la sottoquery non restituisce righe, restituirà 0.

0

Ci sono alcuni problemi con questo. Per cominciare è difficile riprodurre senza lo schema per training_transactions.

Inoltre dalla tua descrizione e schema sembrerebbe che vuoi un join interno sulla prima tabella. training avrebbe sempre un'azienda, se ho letto bene. training_details sembrano essere irrilevanti per la query e darebbero un prodotto incrociato se non lo fossero.

Suppongo che l'unione delle transazioni da parte dell'utente sia errata poiché si dispone di un training_transaction_course che presumo sia la chiave esterna corretta.

Il conteggio è errato: non è così che funziona e serve una clausola GROUP BY se si desidera il conteggio.

La clausola WHERE appare corretta per me poiché gli elementi non sono utilizzati in nessun join.

Questo darebbe qualcosa di simile:

SELECT training.course_id, -- everything you put here needs to go in the group by clause 
    count(training_transactions.training_transaction_course) as completed_training_payments 
    FROM training 
    JOIN training_company 
     ON training.course_main = training_company_id 
    LEFT JOIN training_transactions 
     ON training.course_id = training_transactions.training_transaction_course 
    WHERE course_id = ? 
     AND training_transactions.training_transaction_status = 'complete' 
     AND training_transactions.training_transaction_payment_status = 'complete' 
     AND course_enabled = 'enabled' 
    GROUP BY training.course_id, training_transactions.training_transaction_course 

~

0

Il problema è la vostra richiesta sarà mai risultato in più di una riga.

Utilizzare le query raggruppate o nidificate come indicato in altre risposte.

Problemi correlati