Sql server SQL Server使用不同的值在两列中统计数据
我想做一个智能计数操作,这样如果列中的数据相同,那么它将被计数为1 我的桌子是:Sql server SQL Server使用不同的值在两列中统计数据,sql-server,tsql,Sql Server,Tsql,我想做一个智能计数操作,这样如果列中的数据相同,那么它将被计数为1 我的桌子是: dbo.Messages ( FromUserId INT, ToUserId INT ) 数据: 计数应该返回2,因为1,5和5,1在我的算法中是相同的 如何在SQL Server TSQL中编写它 提前感谢。一种方法是使用原始表中的不同值,按FromUserId和ToUserId中最小和最大的值分组。与MySQL不同,SQL Server没有最小和最大的函数,因此我们可以使用CASE表达式
dbo.Messages
(
FromUserId INT,
ToUserId INT
)
数据:
计数应该返回2,因为1,5和5,1在我的算法中是相同的
如何在SQL Server TSQL中编写它
提前感谢。一种方法是使用原始表中的不同值,按FromUserId和ToUserId中最小和最大的值分组。与MySQL不同,SQL Server没有最小和最大的函数,因此我们可以使用CASE表达式
SELECT CASE WHEN t.FromUserId < t.ToUserId THEN t.FromUserId ELSE t.ToUserId END,
CASE WHEN t.FromUserId < t.ToUserId THEN t.ToUserId ELSE t.FromUserId END,
COUNT(*) AS duplicateCount
FROM
(
SELECT DISTINCT FromUserId, ToUserId
FROM dbo.Messages
) t
GROUP BY CASE WHEN t.FromUserId < t.ToUserId THEN t.FromUserId ELSE t.ToUserId END,
CASE WHEN t.FromUserId < t.ToUserId THEN t.ToUserId ELSE t.FromUserId END
这很有效:
CREATE TABLE #Messages
(
FromUserId INT,
ToUserId INT
);
INSERT #Messages VALUES(1, 5), (2, 20), (5, 1), (1, 5);
SELECT COUNT(*)
FROM (
SELECT M1.FromUserId, M1.ToUserId
FROM #Messages AS M1
EXCEPT
SELECT M2.ToUserId, M2.FromUserId
FROM #Messages AS M2
WHERE M2.ToUserId > M2.FromUserId
) AS T;
带有EXCEPT的派生表将删除重复项,然后它只计算所谓的唯一值。请记住,除了删除所有重复项之外,这里不需要使用不同的关键字
派生表的结果:
FromUserId ToUserId
---------- --------
1 5
2 20
您可以在此处检查此查询的工作方式:在SQL Server 2008及更高版本上,这应该可以工作:
SELECT distinct
(SELECT Min(v) FROM (VALUES (FromUserId), (ToUserId)) AS value(v)) as UserIdMin,
(SELECT Max(v) FROM (VALUES (FromUserId), (ToUserId)) AS value(v)) as UserIdMax
FROM dbo.Messages
信用证:我认为它不符合A/C。如果您删除计数并保持唯一性,它会返回1和5,这似乎是错误的。1,5和5,1应该被视为相同的。@EvaldasBuinauskas:用户要求计数,在本例中返回2,您是否看到了演示。但碰巧它带来了2。编辑数据后,您的查询将不再有效。它将返回不正确的计数。@EvaldasBuinauskas:谢谢,我在想用户问题中的这一行,whole time count应该返回2,现在更新这是一个很好的答案。要添加内容,不需要两个单独的子查询,可以使用交叉应用来返回最小值和最大值。下面是一个例子:
FromUserId ToUserId
---------- --------
1 5
2 20
SELECT distinct
(SELECT Min(v) FROM (VALUES (FromUserId), (ToUserId)) AS value(v)) as UserIdMin,
(SELECT Max(v) FROM (VALUES (FromUserId), (ToUserId)) AS value(v)) as UserIdMax
FROM dbo.Messages