2016-12-15 10 views
0

У меня есть таблица под названием properties (p) и другая таблица, называемая сертификатами (c). Для каждого свойства может быть не более одного сертификата или никакого сертификата. Мне нужно создать запрос, который использует соединение, и отображает только один сертификат из таблицы сертификатов для каждого свойства. Один сертификат, который показан, должен быть с самой последней датой истечения срока действия. В таблице сертификатов есть поле с именем «certificate_expiry_date». Простым соединением будет p.property_id = c.certificate_property, но в настоящее время он выводит все сертификаты.MySQL - добавить предложения влево присоединиться

Мой запрос Покушение

Вот мой запрос до сих пор;

SELECT DISTINCT t.tenancy_property, t.*, p.*, c.* FROM tenancy t 
INNER JOIN property p 
on t.tenancy_property = p.property_id 
LEFT JOIN 
(
    SELECT * 
    FROM certificate 
    WHERE certificate_expiry_date > CURDATE() 
    ORDER BY certificate_expiry_date DESC 
    LIMIT 1 
) c ON p.property_id = c.certificate_property 
WHERE t.tenancy_type='1' AND p.property_mains_gas_supply='1' AND p.property_availability='2' ORDER BY t.tenancy_id DESC LIMIT {$startpoint} , {$per_page} 

Этот запрос выполняется нормально, но, похоже, не учитывает левое соединение в таблице сертификатов.

Структура таблицы для таблицы certificate

CREATE TABLE IF NOT EXISTS `certificate` (
    `certificate_id` int(11) NOT NULL AUTO_INCREMENT, 
    `certificate_property` int(11) DEFAULT NULL, 
    `certificate_type` tinyint(4) DEFAULT NULL, 
    `certificate_reference` varchar(255) COLLATE utf8_bin DEFAULT NULL, 
    `certificate_start_date` date DEFAULT NULL, 
    `certificate_expiry_date` date DEFAULT NULL, 
    `certificate_notes` text COLLATE utf8_bin, 
    `certificate_renewal_instructed` tinyint(4) DEFAULT NULL, 
    `certificate_renewal_contractor` int(11) DEFAULT NULL, 
    PRIMARY KEY (`certificate_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=219 ; 
+0

Классический «выберите верхнюю часть на группу». – shmosel

+2

Я добавил тег [tag: great-n-per-group]. На этот вопрос ответили сотни раз. Просто следуйте ссылке тега. –

+0

@BillKarwin Он выбирает только один элемент, поэтому нет групп. – Barmar

ответ

0

Обновленный ответ с обновленной информацией

Что-то вроде этого?

(Примечание: Этот ответ подразумевает, что каждое свойство имеет по крайней мере один сертификат, или же подзапрос qMostRecentExpire может не)

select 
    p.property_id 
    , p.* 
    , (select 
      c.certificate_id 
     from 
      certificates as c 
     where 
      c.certificate_property = p.property_id -- all the cert of this property 
      and c.certificate_expiry_date < CURDATE() -- cert has expired 
     order by c.certificate_expiry_date desc  
     limit 1          -- most recent one 
    ) as qMostRecentExpire 
from 
    properties as p 

Обновленный ответ после того, зная, что некоторые свойства могут не иметь никаких сертификатов

select 
    p.property_id 
    , p.* 
    , (select 
      c.certificate_id 
     from 
      certificates as c 
     where 
      c.certificate_property = p.property_id -- all the cert of this property 
      and c.certificate_expiry_date < CURDATE() -- cert has expired 
     order by c.certificate_expiry_date desc  
     limit 1          -- most recent one 
    ) as qMostRecentExpire 
from 
    properties  as p 
    , certificates as c        -- inner join : properties that 
where             -- has not cert will be dropped 
    p.property_id = c.certificate_property    
+0

См. Обновление к моему сообщению, это может помочь вам улучшить ваш ответ –

+0

Я обновил свой ответ выше. У меня нет ваших таблиц, поэтому я не могу проверить свой запрос. Но это может дать вам некоторые идеи. Удачи! – leeyuiwah

+0

Спасибо за ваши усилия, но, к сожалению, не гарантировано, что каждое свойство имеет хотя бы один сертификат. –

0

Если нам нужно вернуть только один или два столбца из таблицы certificates, мы можем иногда использовать коррелированные подзапросы в списке SELECT.

Этот подход имеет некоторые последствия для производительности для больших таблиц; но для некоторых случаев использования с соответствующими индексами это может быть приемлемым подходом.

SELECT p.id 
     , p.somecol 

     , (SELECT c.col 
      FROM certificate c 
      WHERE c.property_id = p.id 
      ORDER BY c.date_added DESC, c.id DESC 
      LIMIT 1 
     ) AS most_recent_cert_col 

     , (SELECT c.date_added 
      FROM certificate c 
      WHERE c.property_id = p.id 
      ORDER BY c.date_added DESC, c.id DESC 
      LIMIT 1 
     ) AS most_recent_cert_date_added 

    FROM property p 
    WHERE ... 
ORDER BY ... 
+0

См. Обновление к моему сообщению.Помогает ли дополнительная информация улучшить ваш ответ в любом случае? Мне нужно вернуть все столбцы из таблицы сертификатов –

+0

@MichaelLB: Если вам нужно вернуть * все * столбцов из таблицы 'certificate', то, как указал Билл Карвин в своем комментарии, это знакомый вопрос, который был ответил * десятки * раз. – spencer7593