1

MySQL に次の 3 つのテーブルがあります。

+----------------------------------------------+
| ComputerConfigs                              |
+----------+-----------------------------------+
| ConfigID | ComputerID | LastChangeDate | ... |
+----------+-----------------------------------+

+-------------------+
| Software          |
+------------+------+
| SoftwareID | Name |
+------------+------+

+-----------------------------------------------------+
| ComputerHasSoftware                                 |
+------------+----------------------------------------+
| ComputerID | ConfigID | SoftwareID | LastChangeDate |
+------------+----------------------------------------+

ComputerConfig が変更されるたびに、新しい行が に書き込まれComputerConfigsます。ですから、過去からのすべての変化も見ることができます。

現在、ソフトウェアの変更も追跡しようとしています。これはそれほど頻繁には発生しないためComputerHasSoftware、誰かが実際に何かを追加または削除した場合にのみ、新しい行をテーブルに保存したいと考えています。

インストールされているソフトウェアを使用して(ComputerConfigs過去から現在まで)すべてを返すクエリを書きたいと思います。したがって、に属する行が追加されていない場合は、ComputerConfig のタイムスタンプのに最新のものを取得する必要があります。ComputerHasSoftwareComputerConfig

3 つのテーブルを単純に結合する、次のようなクエリを実行することを考えました。

SELECT 
FROM ComputerConfigs
LEFT OUTER JOIN ComputerHasSoftware
             ON ComputerHasSoftware.ComputerID = ComputerConfigs.ComputerID
LEFT OUTER JOIN Software
             ON Software.SoftwareID = ComputerHasSoftware.ComputerID

しかし、ご想像のとおり、このクエリは間違った結果を導きます。これは、古いソフトウェアをそこに属さないコンピュータに関連付けるためです。結合条件を に変更してComputerHasSoftware.ConfigID = ComputerConfigs.ConfigIDも機能しません。これは、データが提供されていないものを見逃し、代わりに利用可能な最新のものにフォールバックする必要があるためです。

これを達成するためにクエリを変更するにはどうすればよいですか? それとも、サブクエリを使用したより良い解決策がありますか?

4

2 に答える 2

1

MySQL がこれを高速化するために使用できるトリックは限られています。相関サブクエリを使用しても機能します、パフォーマンスを確認する必要があります。

SELECT
  *
FROM
  ComputerConfigs
LEFT OUTER JOIN
  ComputerHasSoftware
    ON ComputerHasSoftware.ComputerID = ComputerConfigs.ComputerID
    AND ComputerHasSoftware.LastChangeDate = (
                                              SELECT MAX(LastChangeDate)
                                                FROM ComputerHasSoftware
                                               WHERE ComputerID = ComputerConfigs.ComputerID
                                                 AND LastChangeDate <= ComputerConfigs.LastChangeDate
                                             )
LEFT OUTER JOIN
  Software
    ON Software.SoftwareID = ComputerHasSoftware.ComputerID 
于 2012-05-09T17:32:09.260 に答える
0

ギャップ日付期間を選択する必要があります:

select 
   ConfigID
  ,f.LastChangeDate as fromDate
  ,coalesce( min( t.LastChangeDate ), now() ) as toDate
from 
  ComputerConfigs f
     left outer join
  ComputerConfigs t 
    on f.ComputerID = t.ComputerID
where
  t.LastChangeDate > f.LastChangeDate
group by 
  ConfigID, f.LastChangeDate

次に、次の方法で結合します。

SELECT *
FROM ComputerConfigs
LEFT OUTER JOIN ComputerHasSoftware
             ON ComputerHasSoftware.ComputerID = ComputerConfigs.ComputerID
LEFT OUTER JOIN ( above subquery) S
             ON S.ConfigID = ComputerConfigs.ConfigID
LEFT OUTER JOIN Software
             ON Software.ComputerID = ComputerHasSoftware.ComputerID and
                Software.LastChangeDate between S.fromDate and S.toDate

above subquery最初のクエリに置き換える必要があることに注意してください。betweenあなたの質問では、条件または< or条件が必要かどうかわかりません>。ニーズに合わせて自由にクエリに対応できます。楽しみ。

于 2012-05-09T17:39:57.250 に答える