我有两个表:车辆(Id,VIN)和图像(Id,VehicleId,名称,默认)。我需要选择车辆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将显示其默认图像,因为它已设置。我希望这能解决问题。
答案 0 :(得分:3)
WHERE Images.Default = 1 OR Images.Default IS NULL
where子句将左连接转换为内连接,因为它需要匹配的记录才能满足条件。
答案 1 :(得分: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表中将列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 );
这是解决方案。
首先,我们需要一个查询,每个车辆获得一个图像行,如果有,则选择默认值。
我们通过按DEF的降序排序图像(所以1s位于顶部),然后按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 |
+----+-------------------+------+-----------+------+------+
答案 2 :(得分: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将乘以默认图像的数量。如果每辆车最多只有一个默认图像,这不是问题。
答案 3 :(得分: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
答案 4 :(得分: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也将捕获没有匹配图像并且左连接填充空值的情况。