这是否需要游标或基于集合的方法?

时间:2019-03-12 15:38:33

标签: sql

我必须写一个查询,以便我们可以尝试获取自动的每月报告。该查询的基本思想是,首先我们获取与关联公司相关的所有主ID的列表。结果集示例:

abc123
def456
ghi789

从该Master ID列表中,我们需要获取该公司记录中出现两次或两次以上的所有客户电子邮件的列表,这意味着该电子邮件地址可能被误分配或无效。该查询应返回电子邮件地址列表以及它们出现的频率。结果集示例:

ACME Agency abc123 fakeemail@fake.com   2
ACME Agency abc123 thisisonlyatest@info.com 94
ACME Agency abc123 notarealemail@none.com   5
ACME Agency abc123 helloworld@dummy.com 2
ACME Agency abc123 info@info.net 2

从那里,我们需要获取与每个电子邮件地址相关的交易记录-如果一切顺利,我们将获得与上一查询中给出的总数相等的行数-因此,在这种情况下,总共为105行。然后,将这些行添加到临时表中,该表最终将包括每个主行的整个结果集。

在处理这种情况时,我的第一个冲动是转到while循环或游标,因为这是我最熟悉的逻辑。我的研究表明,一般而言,基于集合的方法是必经之路。但是,它也表示,当需要游标时,通常是在必须遍历每一行并执行某些操作的情况下。

我的问题是,是这种情况吗?我是否在设想游标-甚至是双嵌套游标是必不可少的问题,或者在这种情况下是否存在基于集合的方法,是否正确地预见了该问题?

如果需要的话,我可以进行编辑以包含查询,但是这有点像野兽。我想提高其运行时速度,但是如果要正确过滤,我们有数千个Master ID可以循环通过-大约5k。

1 个答案:

答案 0 :(得分:0)

最终有一位高级开发人员向我展示了如何以无游标的方式进行此操作。

我的第一个计划是使用游标进行查询,以浏览我们必须参考的主ID列表。

DECLARE @agency_number NVARCHAR(500)

DECLARE db_cursor CURSOR FOR
SELECT Master_Agency_Number
FROM temptablelist

OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @agency_number

WHILE @@FETCH_STATUS = 0
BEGIN

一旦进入循环,我将根据代理商编号将相关的电子邮件地址拉入临时表,然后根据电子邮件表拉出另一组数据,最后将该结果集附加到最终的临时表中最终将包含所有主代理机构ID的整个结果集。它的工作比我最初的尝试要好-我们在45分钟内获得了正确的数据。但是对于我们需要的,我们需要更快。

另一个开发人员终于向我展示了另一种方法。

我们将主代理机构ID和我们需要的其他一些信息加载到临时表中,而不是使用它来启动游标。

INSERT 
emaillist SELECT dm.[Master_Agency_Number]
,vwp.[Email_Address]
,count(*) as TotalOccurrence
FROM   table1 vwP
INNER JOIN table2 dm
ON vwP.AgencyNum = dm.Agency_Number
WHERE
   --filter for active policies
   AND vwP.CurrentTypeAct <> 'Canceled'
   AND vwP.Email_Address is not NULL
   group by dm.[Master_Agency_Number], vwp.[Email_Address]
   HAVING count(*) >= 2
   order by dm.[Master_Agency_Number] asc, count(*) desc

从那里,我们编写了另一个查询,对这个临时表进行了内部联接,以确保我们仅从相关机构处提取数据,然后使用IN子句确保从数据库中提取数据。正确的电子邮件地址。

SELECT DISTINCT
    [all the column names]
FROM table1 vwP
LEFT JOIN table2 stgA
    ON vwP.AgencyNum = stgA.Agency_Number
INNER JOIN table3 dm
    ON vwP.AgencyNum = dm.Agency_Number
INNER JOIN emaillist 
    ON emaillist.Master_Agency_Number = dm.Master_Agency_Number
WHERE
--filter for active policies
AND vwP.CurrentTypeAct <> 'Canceled'
and stgA.Email_Address is not null 
and vwp.[Email_Address] is not null
AND vwp.[Email_Address] IN (SELECT Email_Address FROM emaillist WHERE 
dm.Master_Agency_Number = emaillist.Master_Agency_Number)
ORDER BY
dm.[Master_Agency_Number], vwp.[Email_Address]

使用INNER JOININ将运行时间缩短到45秒。因此,如果您坚持使用游标,请尝试将两者结合起来以查看是否可以按需要的方式解析数据!