2016-12-15 4 views
0

私はプロパティ(p)と呼ばれるテーブルと証明書(c)と呼ばれるテーブルを持っています。各プロパティに対して1つ以上の証明書が割り当てられていても、全く証明書が存在しなくてもかまいません。結合を使用するクエリを生成する必要があり、プロパティごとに証明書テーブルの証明書が1つだけ表示されます。表示されている1つの証明書は、最新の有効期限の証明書である必要があります。証明書テーブルには、「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

クラシック "グループごとにトップnを選択"。 – shmosel

+2

私は[タグ:グループごとの最高のn]タグを追加しました。この質問は何百回も答えられています。タグのリンクに従ってください。 –

+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

あなたの努力に感謝しますが、不幸にも各プロパティに少なくとも1つの証明書があることが保証されていません –

0

certificatesテーブルから1つまたは2つの列を返す必要がある場合は、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'テーブルから*すべての列を返す必要がある場合、Bill Karwinがコメントに示したように、これはよく知られている質問です*数十回答えた。 – spencer7593

関連する問題