根据“选择计数(*)分组依据”填充列

时间:2014-02-03 22:16:29

标签: sql-server tsql

我在一个名为@AccountStatRollup的存储过程中创建了一个表。我使用AccountID填充它。我创建了第二个名为@Contacts的表。我用ContactIDs和ContactAccountIDs填充它。我正在尝试使用@Contacts表中的相关联系人填充@ AccountStatRollup.AccountContacts字段。

我已经尝试了一个数字,如果sql更新语句并失败。这是我试过的最后一句话:

感谢您的帮助。

凯文

Declare @AccountStatRollup TABLE(
    AccountID varchar(30),
    AccountContacts int
)
Declare @Contacts TABLE(
    ContactID varchar(30),
    ContactsAccountID varchar(30)
)

我尝试计算帐户联系人计数

UPDATE @AccountStatRollup a 
    SET a.AccountContacts = (SELECT COUNT(*)FROM @Contacts c GROUP BY c.ContactsAccountID)
    ON c.ContactsAccountID = a.ContactID

谢谢大家! 我设法得到这个代码来保存和执行(Microsoft SQL服务器)

--Calculate Account Contacts count
    UPDATE @AccountStatRollup
    SET AccountContacts = (SELECT COUNT(*) FROM @Contacts 
    WHERE ContactsAccountID = AccountID )

我让存储过程运行了一段时间然后我就把它杀死了。我意识到这对我来说一定是非常低效的。我将使用此示例添加其他列总计。我可能拥有30,000个帐户和16,000个联系人......

我试图让这段代码正常工作,但它无法识别c.ContactsAccountID,无法绕过它。

--Calculate Account Contacts count ver 2      
    UPDATE a
    SET AccountContacts = c.cnt
    FROM @AccountStatRollup a join
         (SELECT COUNT(*) as cnt
          FROM @Contacts c
          GROUP BY c.ContactsAccountID
         ) c
         ON c.ContactsAccountID = a.AccountID;

Msg 207,Level 16,State 1,Procedure AccountStatRollup,56行 列名称“ContactsAccountID”无效。

有没有比我尝试的更有效的计算总数的方法?

谢谢!

凯文

好的,我想出了如何快速完成这项工作。

我使用唯一索引创建了临时表。

- 创建一个本地表来保存帐户统计信息         声明@AccountStatRollup TABLE(             AccountID varchar(18),             AccountContacts int,             独特(AccountID)         );

- 创建一个本地表来保存联系人数据         声明@Contacts TABLE(             ContactID varchar(18),             ContactsAccountID varchar(18),             独特(ContactID)         );

- 创建一个本地表来保存联系人计算数据         声明@tmpAccountCalculation TABLE(             AccountID varchar(18),             AccountName varchar(100),             FieldCount int,             独特(AccountID)         );

- 使用所有AccountID值填充@AccountStatRollup表         INSERT INTO @AccountStatRollup(AccountID)             来自sfAccount的SELECT ID - 使用所有AccountID值填充@Contacts表         INSERT INTO @Contacts(ContactID,ContactsAccountID)             来自sfContact的SELECT ID,ACCOUNTID

- 填充@tmpAccountCalculation表         INSERT INTO @tmpAccountCalculation(AccountID,AccountName,FieldCount)         SELECT dbo.sfAccount.ID,dbo.sfAccount.NAME,COUNT(dbo.sfContact.ACCOUNTID)AS ContactCount         FROM dbo.sfAccount INNER JOIN dbo.sfContact ON dbo.sfAccount.ID = dbo.sfContact.ACCOUNTID         GROUP BY dbo.sfAccount.ID,dbo.sfAccount.NAME HAVING(COUNT(dbo.sfContact.ACCOUNTID)> 0)

- 更新@AccountStatRollup表         更新A.         SET A.AccountContacts = B.FieldCount         来自@AccountStatRollup A.         INNER JOIN @tmpAccountCalculation B ON A.AccountID = B.AccountID

- 测试输出 从@AccountStatRollup中选择*,其中AccountContacts> 0按AccountContacts desc排序

这需要大约1秒才能运行。

...呼

凯文

2 个答案:

答案 0 :(得分:1)

您应该将where条件移动到内部查询,并且不需要该组:

UPDATE @AccountStatRollup a 
  SET
    a.AccountContacts = (
      SELECT
        COUNT(*)
      FROM
        @Contacts c
      where
        c.ContactsAccountID = a.ContactID
  );

答案 1 :(得分:0)

因为您正在使用表变量,所以我假设这是SQL Server。您可以使用update join语法:

以极佳的方式进行更新
UPDATE a
    SET AccountContacts = c.cnt
    FROM @AccountStatRollup a join
         (SELECT COUNT(*) as cnt
          FROM @Contacts c
          GROUP BY c.ContactsAccountID
         ) c
         ON c.ContactsAccountID = a.ContactID;

SQL标准方法应该在几乎所有数据库中都可以使用相关子查询:

UPDATE @AccountStatRollup a 
    SET AccountContacts = (SELECT COUNT(*)
                           FROM @Contacts c
                           WHERE c.ContactsAccountID = a.ContactID
                          );

使用相关子查询时,不需要group by。实际上,包含group by会产生误导,因为它表明可能存在多个组 - 并且在执行语句时会导致错误。