【问题标题】:Count difference between distinct and join over distinct计算 distinct 和 join over distinct 之间的差异
【发布时间】:2014-11-29 17:21:46
【问题描述】:

如何计算不同行的数量减去对这些相同不同行的连接?

如果用户对提交的行没有权限,我需要在触发器之后引发错误。我可以在两个语句中做到这一点,但这似乎效率低下。

DECLARE @AccessibleCount INT =
(
    SELECT
        COUNT(DISTINCT i.[ParentId])
    FROM
        inserted i
    INNER JOIN [SuperSecret].[Parent] AS p ON
        p.[Id] = i.[ParentId] AND
        p.[LockedBy] = @UserId
);

DECLARE @ActualCount INT = (SELECT COUNT(DISTINCT [ParentId]) FROM inserted);
IF (@AccessibleCount <> @ActualCount)
BEGIN
    RAISERROR(...);
    ROLLBACK TRANSACTION;
END

出于性能考虑,我似乎应该对不同的inserted.ParentId 使用子查询来计算这两个计数。我尝试了以下方法,但结果是“无效的对象名称'i'。”

DECLARE @ActualMinusAccessible INT =
(
    SELECT
        COUNT(*)
            -
        (
            SELECT
                COUNT(*)
            FROM
                i
            INNER JOIN [SuperSecret].[Parent] AS p ON
                p.[Id] = i.[ParentId] AND
                p.[LockedBy] = @UserId
        )
    FROM
        (
            SELECT DISTINCT [ParentId] FROM inserted
        ) AS i
);

IF (@ActualMinusAccessible <> 0)
BEGIN
    RAISERROR (...);
    ROLLBACK TRANSACTION;
END

【问题讨论】:

    标签: sql sql-server join sql-server-2008-r2 distinct


    【解决方案1】:

    如果没有错,如果[ParentId]插入,而[SuperSecret].[Parent] 表中不存在,您想Raise Error。尝试像这样更改您的 SQL 查询。

    IF EXISTS (SELECT 1
               FROM   inserted i
               WHERE  NOT EXISTS (SELECT 1
                                  FROM   [SuperSecret].[Parent] a
                                  WHERE  i.[ParentId] = a.[ParentId] AND a.[LockedBy] = @UserId))
      BEGIN
          RAISERROR (...);
          ROLLBACK TRANSACTION;
      END 
    

    IF (SELECT Count(DISTINCT [ParentId]) - (SELECT Count(DISTINCT i.[ParentId])
                                             FROM   inserted i
                                                    INNER JOIN [SuperSecret].[Parent] AS p
                                                            ON p.[Id] = i.[ParentId]
                                                               AND p.[LockedBy] = @UserId)
        FROM   inserted) <> 0
      BEGIN
          RAISERROR (...);
          ROLLBACK TRANSACTION;
      END 
    

    【讨论】:

    • @user1546077 - 是的,你不能在那里引用别名 (i),这是错误的。尝试执行我的答案
    • 谢谢,第一个查询的实际执行计划比第二个要好。第二个查询的实际执行计划与原始查询类似,但在某些(很多?)情况下可能会更好。
    猜你喜欢
    • 2020-03-03
    • 2023-01-12
    • 2013-08-28
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 2010-12-28
    • 2013-11-11
    • 1970-01-01
    相关资源
    最近更新 更多