1

我有两个表:Vehicles(Id, VIN) 和 Images(Id, VehicleId, Name, Default)。我需要选择车辆 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 或 Images.Default 为 NULL

where 子句将左连接转换为内连接,因为它需要匹配的记录来满足条件。

于 2009-08-13T18:11:30.673 回答
2

好的,这是设置:

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 表中将该列重命名DEFAULTDEF

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 );

这就是解决方案。

首先,我们需要一个查询,每辆车获取一个图像行,如果有则选择默认行。

我们通过按 DEF 的降序对图像进行排序(因此 1 位于顶部),然后进行分组VEHICLEID以确保每辆车只有一行。

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上面的查询,以确保我们总是每辆车得到一行:

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 将乘以默认图像的数量。如果每辆车最多有一个默认图像,这不是问题。

于 2009-08-13T18:19:02.903 回答
0

我会做这样的事情来获得没有图像的默认名称。

SELECT
    Vehicles.Id, Vehicles.VIN, COALESCE(Images.Name,'default image 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 OR Images.Name IS NULL
于 2009-08-13T18:22:48.603 回答
0
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 OR Images.Name IS NULL

这假设所有图像都有一个名称。原始查询的问题在于,要求“Images.Default = 1”意味着查询必须匹配图像。允许 Images.Id 为 NULL 也将捕获没有匹配图像并且左连接填充空值的情况。

于 2009-08-13T18:36:10.413 回答