我有包含数百万(可能数十亿)行的表,所以我确实需要高效地进行查询。
在这个查询中,我连接了多个表。所涉及的段是:
LEFT JOIN
dbo.GCSOCTPS dbo_GCSOCTPS ON (GC_TBMED.MED_CLASS_NUM = dbo_GCSOCTPS.CLASS_NUM)
AND (GC_TBMED.MED_SOC_NUM = dbo_GCSOCTPS.SOC_NUM)
AND (GC_TBMED.MED_EFF_DATE = dbo_GCSOCTPS.EFF_DATE)
AND (GC_TBMED.MED_CANC_DATE = dbo_GCSOCTPS.CANC_DATE))
GC_TBMED
格式为日期DATE
,格式dbo_GCSOCTPS
为日期DATETIME
。遗憾的是,由于我们公司使用数据的方式,我无法更改这一点。
比较这些列最有效的方法是什么???CAST
我 CONVERT
见过有人转换成文本格式再比较。我希望有人能根据他们处理海量数据集的经验来指导我。
如果我运行此代码块,我会得到 HDHPQ 的值:
SELECT TOP 200
HDHPQ,
SOC_NUM,
EFF_DATE,
CLASS_NUM,
CANC_DATE
FROM
dbo.GCSOCTPS
WHERE
SOC_NUM = '25521'
AND CLASS_NUM = '37'
AND CANC_DATE IS NULL;
返回结果如下:
HDHPQ SOC_NUM EFF_DATE CLASS_NUM CANC_DATE
N 25521 2025-01-01 00:00:00.000 37 NULL
如果我运行此代码块,我也会得到返回的数据:
SELECT TOP 200
MED_SOC_NUM,
MED_EFF_DATE,
MED_CLASS_NUM,
MED_CANC_DATE
FROM
[dbo].[AS_tblTBMED] GC_TBMED
WHERE
GC_TBMED.MED_SOC_NUM = '25521'
AND GC_TBMED.MED_CLASS_NUM = '37'
AND GC_TBMED.MED_CANC_DATE IS NULL;
返回结果如下:
MED_SOC_NUM MED_EFF_DATE MED_CLASS_NUM MED_CANC_DATE
25521 2025-01-01 37 NULL
每个查询都返回一行。我需要将它们连接起来,以便获取第二个查询中的所有数据以及第一个查询中的 HDHPQ 值。
所以我运行这个查询:
SELECT DISTINCT TOP 200
dbo_GCSOCTPS.HDHPQ,
dbo_GCSOCTPS.SOC_NUM,
dbo_GCSOCTPS.EFF_DATE,
dbo_GCSOCTPS.CLASS_NUM,
dbo_GCSOCTPS.CANC_DATE,
GC_TBMED.MED_SOC_NUM,
GC_TBMED.MED_EFF_DATE,
GC_TBMED.MED_CLASS_NUM,
GC_TBMED.MED_CANC_DATE
FROM
[dbo].[AS_tblTBMED] GC_TBMED
LEFT JOIN
dbo.GCSOCTPS dbo_GCSOCTPS ON (GC_TBMED.MED_CLASS_NUM = dbo_GCSOCTPS.CLASS_NUM)
AND (GC_TBMED.MED_SOC_NUM = dbo_GCSOCTPS.SOC_NUM)
AND (GC_TBMED.MED_EFF_DATE = CAST(dbo_GCSOCTPS.EFF_DATE as DATE))
AND (GC_TBMED.MED_CANC_DATE = CAST(dbo_GCSOCTPS.CANC_DATE as DATE))
WHERE
GC_TBMED.MED_SOC_NUM = '25521'
AND GC_TBMED.MED_CLASS_NUM = '37'
AND GC_TBMED.MED_CANC_DATE IS NULL
AND dbo_GCSOCTPS.EFF_DATE >= '2025-01-01';
返回的是一个空的记录集。如果我注释掉连接语句中的两个日期,就能得到数据。所以,我的假设是日期字段没有完全相等,因为它们是相等的,所以如果查询中包含它们,我应该能得到数据。
这里至少有两个问题:
<anything> = NULL
永远不会成立,因此加入将失败。您可能需要类似以下内容的内容:
不过,还有几行比较可疑:
CAST(gcs.EFF_DATE as DATE)
如果 EFF_DATE 不包含小时等,你可以跳过转换tbm.MED_CLASS_NUM = '37'
为什么使用'37'
而不只是37
用于看起来像数字的列?对于这些旧的数据类型,我会选择cast
我不明白为什么这会增加任何开销。
什么让它变得高效?索引
所以您需要做的就是让它们可索引。
这意味着您不能在日期和日期时间字段周围使用任何包装函数(例如将它们转换为字符串或整数)
有一些无害的异常,例如 DateAdd()。在寻找范围时它仍然是范围。
所以使用
DateTime >= Date AND DateTime < DATEADD(DAY, 1, Date)
很好..
并且我永远不会使用类似的东西;
WHERE CAST(DateTimeColumn AS DATE) = DateColumn
正如其他人提到的,数据中 CANC_DATE 的 NULL 值阻止了您的返回。尝试将 NULL 转换为实际日期值: