计算 distinct 和 join over distinct 之间的差异
Posted
技术标签:
【中文标题】计算 distinct 和 join over distinct 之间的差异【英文标题】:Count difference between distinct and 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
【问题讨论】:
【参考方案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),这是错误的。尝试执行我的答案 谢谢,第一个查询的实际执行计划比第二个要好。第二个查询的实际执行计划与原始查询类似,但在某些(很多?)情况下可能会更好。以上是关于计算 distinct 和 join over distinct 之间的差异的主要内容,如果未能解决你的问题,请参考以下文章
SQL Server count() over() with distinct
分区函数 COUNT() OVER 可能使用 DISTINCT
论文精读《Random Sampling over Joins Revisited》
count(distinct) over (partition by... 在 Oracle SQL 中不起作用