SQL 左外连接的替代方法
SQL Alternative to left outer join
在性能方面,这是替代 LEFT OUTER JOIN 的好方法吗?是最好的吗?
SELECT a.PRODUCT_ID
,a.PROD_NAME
,a.PRODUCTTYPE_ID
,a.SUPPLIER_ID
,t.PRODTYPE_NAME
,s."NAME" SUPPLIER_NAME
FROM PRODUCT a
INNER JOIN (
SELECT NULL PRODUCTTYPE_ID
,NULL PRODTYPE_NAME
FROM rdb$database
UNION ALL
SELECT PRODUCTTYPE_ID
,PRODTYPE_NAME
FROM PRODUCTTYPE
) t
ON (t.PRODUCTTYPE_ID = a.PRODUCTTYPE_ID) OR (t.PRODUCTTYPE_ID IS NULL AND a.PRODUCTTYPE_ID IS NULL)
INNER JOIN (
SELECT NULL SUPPLIER_ID
,NULL "NAME"
FROM rdb$database
UNION ALL
SELECT SUPPLIER_ID
,"NAME"
FROM SUPPLIER
) s
ON (s.SUPPLIER_ID = a.SUPPLIER_ID) OR (s.SUPPLIER_ID IS NULL AND a.SUPPLIER_ID IS NULL)
PRODUCT_ID、PRODUCTTYPE_ID、SUPPLIER_ID 中 Table PRODUCT 及其各自表的索引
没有!
你应该使用 left join
。以下是您的方法(几乎很有可能)变得更糟的一些原因:
- 您正在执行多个连接而不是单个连接。单个连接应该更快。
- 您在
on
子句中有 or
。哎呀!那是性能杀手。
union all
before join 的使用使得使用索引变得更加困难。而且统计信息很可能会关闭(虽然我不知道Firebird是否使用统计信息来优化查询)。
- 您的复杂查询不太可能使用索引。
一个简单的 left join
应该使用索引并且具有更好的性能。
如果以下查询会为您提供与您所显示的相同的功能,请改用它
SELECT a.PRODUCT_ID, a.PROD_NAME, a.PRODUCTTYPE_ID, a.SUPPLIER_ID ,
t.PRODTYPE_NAME, s."NAME" SUPPLIER_NAME
FROM PRODUCT a
left join PRODUCTTYPE P ON P.PRODUCTTYPE_ID=a.PRODUCTTYPE_ID
left join SUPPLIER S ON s.SUPPLIER_ID=a.SUPPLIER_ID
您可以看到您没有联合(甚至您应该使用的 UNION ALL)——所以这会更快。
在性能方面,这是替代 LEFT OUTER JOIN 的好方法吗?是最好的吗?
SELECT a.PRODUCT_ID
,a.PROD_NAME
,a.PRODUCTTYPE_ID
,a.SUPPLIER_ID
,t.PRODTYPE_NAME
,s."NAME" SUPPLIER_NAME
FROM PRODUCT a
INNER JOIN (
SELECT NULL PRODUCTTYPE_ID
,NULL PRODTYPE_NAME
FROM rdb$database
UNION ALL
SELECT PRODUCTTYPE_ID
,PRODTYPE_NAME
FROM PRODUCTTYPE
) t
ON (t.PRODUCTTYPE_ID = a.PRODUCTTYPE_ID) OR (t.PRODUCTTYPE_ID IS NULL AND a.PRODUCTTYPE_ID IS NULL)
INNER JOIN (
SELECT NULL SUPPLIER_ID
,NULL "NAME"
FROM rdb$database
UNION ALL
SELECT SUPPLIER_ID
,"NAME"
FROM SUPPLIER
) s
ON (s.SUPPLIER_ID = a.SUPPLIER_ID) OR (s.SUPPLIER_ID IS NULL AND a.SUPPLIER_ID IS NULL)
PRODUCT_ID、PRODUCTTYPE_ID、SUPPLIER_ID 中 Table PRODUCT 及其各自表的索引
没有!
你应该使用 left join
。以下是您的方法(几乎很有可能)变得更糟的一些原因:
- 您正在执行多个连接而不是单个连接。单个连接应该更快。
- 您在
on
子句中有or
。哎呀!那是性能杀手。 union all
before join 的使用使得使用索引变得更加困难。而且统计信息很可能会关闭(虽然我不知道Firebird是否使用统计信息来优化查询)。- 您的复杂查询不太可能使用索引。
一个简单的 left join
应该使用索引并且具有更好的性能。
如果以下查询会为您提供与您所显示的相同的功能,请改用它
SELECT a.PRODUCT_ID, a.PROD_NAME, a.PRODUCTTYPE_ID, a.SUPPLIER_ID ,
t.PRODTYPE_NAME, s."NAME" SUPPLIER_NAME
FROM PRODUCT a
left join PRODUCTTYPE P ON P.PRODUCTTYPE_ID=a.PRODUCTTYPE_ID
left join SUPPLIER S ON s.SUPPLIER_ID=a.SUPPLIER_ID
您可以看到您没有联合(甚至您应该使用的 UNION ALL)——所以这会更快。