我有一个表(可以称之为audit
),看起来像这样:选择从范围内的最低日期和排除另一个范围
+--------------------------------------------------------------------------+
| id | recordId | status | mdate | type | relatedId |
+--------------------------------------------------------------------------+
| 1 | 3006 | A | 2013-04-03 23:59:01.275 | type1 | 1 |
| 2 | 3025 | B | 2013-04-04 00:00:02.134 | type1 | 1 |
| 3 | 4578 | A | 2013-04-04 00:04:30.033 | type2 | 1 |
| 4 | 7940 | C | 2013-04-04 00:04:32.683 | type1 | <NULL> |
| 5 | 3006 | D | 2013-04-04 00:04:32.683 | type1 | <NULL> |
| 6 | 4822 | E | 2013-04-04 00:04:32.683 | type2 | <NULL> |
| 7 | 3006 | A | 2013-04-04 00:06:54.033 | type1 | 2 |
| 8 | 3025 | C | 2013-04-04 00:06:54.033 | type1 | 2 |
...和对数百万行的。而另一张表,我们将拨打related
:
+-------------+
| id | source |
+-------------+
| 1 | src_X |
| 2 | src_Y |
| 3 | src_Z |
| 4 | src_X |
| 5 | src_X |
......并开启数十万行。
这两个表格上的列数多于这些列,但这是我们需要描述问题的全部内容。列relatedId
加入related
表。 recordId
也加入到另一个表中,并且audit
中将有多个条目与recordId
相同。
我试图创建将产生以下输出的查询:
+-----------------+
| source | count |
+-----------------+
| src_X | 1643 |
| src_Y | 255 |
| NULL | 729 |
+-----------------+
的计数的记录中audit
数量已经给定type
(如"type1"
),是一个集内的状态(例如,"A", "B", "C"
),然后将其外部加入related
并按source
分组。
美中不足的是,我只希望包括audit
是在特定日期范围内的内记录,而我也只是想从audit
加入到related
在该范围内,最早的条目为每个recordId
。此外,我想忽略任何与type
和status
条件匹配的记录,但是具有相同的recordId
的条目比日期范围更早。
所以,从上面的例子中的数据阐明:可以说,我想的类型的type1
和"A", "B", "C"
与2013-04-04
到2013-04-05
日期范围的状态值。第2行和第4行将包含在计数中。第3行被排除,因为它有不正确的type
。由于状态不正确,第5行被排除。第6行被排除,因为状态和类型都不正确。排除第1行,因为它在日期范围之外。第7行也被排除,因为还有一行(第1行)与状态和类型标准相匹配,并且具有相同的recordId
,该行比日期范围的开始时间更早。第8行被排除,因为第8行和第2行具有相同的recordId
并符合标准,但我们只计算范围内两个最旧的记录。
换句话说,我想只计算给定recordId的条目第一次出现在表中并且在目标日期范围内。
我们已经想出了以下内容:
WITH data (recordId, id) AS (
SELECT a.recordId, MIN(a.id)
FROM audit a
WHERE a.status in ('A','B','C')
AND type = 'type1'
GROUP BY a.recordId
)
SELECT r.source, COUNT(*)
FROM data d
JOIN audit a ON d.id = a.id
LEFT JOIN related r ON a.relatedId = r.id
WHERE a.mdate >= '2013-04-04 00:00:00.000'
and a.mdate < '2013-04-05 00:00:00.000'
GROUP BY r.source
这将MSSQL Server 2008上运行,目前依赖于一个事实,即审计表ID是自动生成的。由于id是在插入记录时生成的,并且mdate也是插入时间戳,并且记录一旦插入就不会更新,所以我认为这是正确的。该查询似乎给出了有限的一组测试数据的正确输出,但我希望得到第二个意见。
- 此查询是否正常?
- 其性能可以提高吗?
计算表格表达式中的日期范围可能会提高性能。 –
好点。将'AND a.mdate <'2013-04-05 00:00:00.000''添加到计算表中将有助于限制它返回的记录数。 –
为了提高查询性能,请考虑索引。在WHERE Clause Fields,Join Fields上使用索引,然后再次测试性能。 – 2013-06-26 11:58:25