我已经编写了一个报告查询,该查询旨在从系统事务日志(transaction_log)中提取一些信息,同时还从第二个表(location_table)中查找主值 - 这并不总是存在,有时master_location 或 location_id 字段可以为 NULL。
我提出了下面的查询,它产生了我想要的结果,尽管自从将“master_location”列添加到查询后运行报告需要更长的时间。
我相信通过放弃 SELECT 语句中的子查询并使用连接来代替,查询/报告的性能可能会得到提高,但我目前对 SQL 很生疏,无法让它工作。
任何人都可以建议改进此查询以提高性能吗?
SELECT
transaction_type,
description,
id_num,
product_id,
quantity,
location_id,
CASE WHEN transaction_log.location_id IS NOT NULL
THEN ( SELECT TOP 1
master_location_id
FROM location_table t1
WHERE t1.location_id = transaction_log.source_location_id
AND master_location_id IS NOT NULL
)
ELSE NULL
END as master_location,
dummy_value,
employee_id,
FROM
transaction_log WITH (NOLOCK)
我尝试了如下的连接,它返回了 2000 多行(与上面的查询相比)。我是否应该在 WHERE 子句中进一步过滤结果?
SELECT
transaction_type,
description,
id_num,
product_id,
quantity,
location_id,
master_location_id,
dummy_value,
employee_id,
FROM
transaction_log t1 WITH (NOLOCK)
INNER JOIN ( SELECT location_id,
master_location_id
FROM location_table) t2
ON t1.location_id = t2.location_id
情况
transaction_log.location_id
有时可能是 NULL
,因此您需要确保获得具有 NULL
位置的事务日志条目。这意味着您需要一个外部联接。location_table.master_location_id
始终彼此相同或 NULL
,因此您需要缩小此列表的范围,以便每个 location_id
、master_location_id
组合只有一行。master_location_id
有时可能是NULL
,因此,在缩小列表范围时,您需要去掉NULL
值。正如下面的注释中所述,所有这些都可以拔出。一个解决方案
SELECT
T_LOG.transaction_type,
T_LOG.description,
T_LOG.id_num,
T_LOG.product_id,
T_LOG.quantity,
T_LOG.location_id,
U_LOC.master_location_id,
T_LOG.dummy_value,
T_LOG.employee_id,
FROM
transaction_log T_LOG WITH (NOLOCK)
LEFT OUTER JOIN (
SELECT T_LOC.location_id,
T_LOC.master_location_id
FROM location_table T_LOC
WHERE T_LOC.master_location_id IS NOT NULL
GROUP BY T_LOC.location_id,
T_LOC.master_location_id
) U_LOC
ON T_LOG.location_id = U_LOC.location_id
;
注意: 请考虑下表中的
location_table
值:
+-------------+--------------------+
| location_id | master_location_id |
+-------------+--------------------+
| 10 | 3 |
| 10 | 3 |
| 20 | NULL |
| 30 | 7 |
| 30 | NULL |
+-------------+--------------------+
删除所有
NULL
master_location_id
行并按两列分组会产生以下效果:
+-------------+--------------------+
| location_id | master_location_id |
+-------------+--------------------+
| 10 | 3 |
| 30 | 7 |
+-------------+--------------------+
location_id
为 20 的行明显丢失。但是,如果该值在那里,master_location_id
将是 NULL
。由于它不存在,因此 LEFT OUTER JOIN
无论如何都会为其返回 NULL
值。所以没有问题。
只有当您想要以不同于
location_table
中的 NULL
值的方式解释 location_table.master_location_id
中缺失的行时,才会出现问题。这超出了这个问题的范围。