1

Vehicles(Id、VIN)とImages(Id、VehicleId、Name、Default)の2つのテーブルがあります。テーブルに表示する車両のVINとそのデフォルトの画像を選択する必要があります。私が抱えている問題は、デフォルトの画像が設定されていない場合でも、表示する画像が存在する場合はそれを選択したいということです。画像が存在しない場合でも、車両情報も表示する必要があります。これが私がこれまでに持っているものです:

SELECT
    Vehicles.Id, Vehicles.VIN, Images.Name AS Image,
    (SELECT COUNT(*) FROM Images WHERE VehicleId = Vehicles.Id) AS ImageCount
FROM
    Vehicles
LEFT JOIN
    Images ON Images.VehicleId = Vehicles.Id
WHERE
    Images.Default = 1

このステートメントは、デフォルトの画像がある車両を表示しますが、デフォルトが設定されていない場合は何も表示しません。何を変更する必要がありますか?

編集*

私の問題をよりよく説明するために、ここにいくつかのテストデータがあります:

VEHICLES:
ID VIN
1  12341234123412341
2  23452345234523452
3  34534534534534534

IMAGES:
ID VEHICLEID NAME DEFAULT
1  1         a    1
2  1         b    0
3  2         c    0
4  2         d    0

車両2にはデフォルトがありませんが、表示する画像を選択してほしいです。また、車両3には画像がまったくありませんが、画像なしでテーブルに表示する必要があります。車両1は設定されているため、デフォルトの画像が表示されます。これで問題が解決することを願っています。

4

5 に答える 5

3

WHERE Images.Default = 1 OR Images.Default IS NULL

where句は、基準を満たすために一致するレコードを必要とするため、左結合を内部結合に変換します。

于 2009-08-13T18:11:30.673 に答える
2

OK、セットアップは次のとおりです。

mysql> create table VEHICLES ( ID INT PRIMARY KEY, VIN CHAR( 17 ) );
mysql> INSERT INTO VEHICLES ( ID, VIN ) VALUES( 1, '12341234123412341' );
mysql> INSERT INTO VEHICLES ( ID, VIN ) VALUES( 2, '23452345234523452' );
mysql> INSERT INTO VEHICLES ( ID, VIN ) VALUES( 3, '34534534534534534' );

IMAGES テーブルの列の名前を次のように変更する必要があったことに注意してDEFAULTください。DEF

mysql> CREATE TABLE IMAGES ( ID INT PRIMARY KEY, VEHICLEID INT, NAME VARCHAR(20), DEF INT );
mysql> INSERT INTO IMAGES( ID, VEHICLEID, NAME, DEF ) VALUES( 1, 1, 'a', 1 );
mysql> INSERT INTO IMAGES( ID, VEHICLEID, NAME, DEF ) VALUES( 2, 1, 'b', 0 );
mysql> INSERT INTO IMAGES( ID, VEHICLEID, NAME, DEF ) VALUES( 3, 2, 'c', 0 );
mysql> INSERT INTO IMAGES( ID, VEHICLEID, NAME, DEF ) VALUES( 4, 2, 'd', 0 );

そして、ここに解決策があります。

まず、車両ごとに 1 つの画像行を取得するクエリが必要です。存在する場合は、既定の画像を選択します。

これは、DEF の降順で画像を並べ替え (1 が一番上になるように)、VEHICLEID車両ごとに 1 行だけになるようにグループ化することで行います。

mysql> SELECT * FROM ( SELECT * FROM IMAGES ORDER BY DEF DESC ) sortedimages GROUP BY VEHICLEID;
+----+-----------+------+------+
| ID | VEHICLEID | NAME | DEF  |
+----+-----------+------+------+
|  1 |         1 | a    |    1 | 
|  3 |         2 | c    |    0 | 
+----+-----------+------+------+

VEHICLES次に、テーブルから選択しLEFT OUTER JOIN、上記のクエリに対して、車両ごとに常に 1 つの行を取得するようにします。

mysql> SELECT * FROM VEHICLES LEFT OUTER JOIN ( SELECT * FROM ( SELECT * FROM IMAGES ORDER BY DEF DESC ) sortedimages GROUP BY VEHICLEID ) defaultimages ON VEHICLES.ID = defaultimages.VEHICLEID;
+----+-------------------+------+-----------+------+------+
| ID | VIN               | ID   | VEHICLEID | NAME | DEF  |
+----+-------------------+------+-----------+------+------+
|  1 | 12341234123412341 |    1 |         1 | a    |    1 | 
|  2 | 23452345234523452 |    3 |         2 | c    |    0 | 
|  3 | 34534534534534534 | NULL |      NULL | NULL | NULL | 
+----+-------------------+------+-----------+------+------+
于 2009-08-13T20:11:39.873 に答える
0

このクエリを次のように記述します。

SELECT v.Id, v.VIN, 
  GROUP_CONCAT(IF(i.Default=1, i.Name, NULL)) AS ImageName,
  COUNT(i.Id) AS ImageCount
FROM Vehicles v
LEFT JOIN Images i ON (i.VehicleId = v.Id AND i.Default = 1)
GROUP BY v.Id;

デフォルトとしてマークされた画像がない場合でも、画像を表示したいというご要望を承りました。これを行うソリューションは次のとおりです。

SELECT v.Id, v.VIN, 
  COALESCE(i1.Name, MIN(i2.Name)) AS ImageName,
  COUNT(i2.Id) AS ImageCount
FROM Vehicles v
LEFT JOIN Images i1 ON (i1.VehicleId = v.Id AND i1.Default = 1)
LEFT JOIN Images i2 ON (i2.VehicleId = v.Id)
GROUP BY v.Id;

デフォルトの画像がない場合に表示する画像を指定していません。そこで、イメージ名をアルファベット順に表示する表現を勝手にデザインしました。

また、このクエリの i1 と i2 の間にデカルト積があることにも注意してください。特定の車両に対して複数のデフォルト画像をマークしないと仮定しますが、そうすると、予期しない結果が得られます。たとえば、ImageCount がデフォルト画像の数で乗算されます。車両ごとに最大 1 つのデフォルト イメージがある場合、これは問題になりません。

于 2009-08-13T18:19:02.903 に答える