【问题标题】:MS SQL Server 2008 query - doesn't get proper send and received message countMS SQL Server 2008 查询 - 没有得到正确的发送和接收消息计数
【发布时间】:2020-07-30 13:30:22
【问题描述】:
SELECT DISTINCT
    U.UserId as 'Id', 
    U.FullName as 'Name',
    (SELECT COUNT(*) FROM [Conversation] 
     WHERE FromUserId = 'user1' AND ToUserId = U.UserId) 'SentCount',
    (SELECT COUNT(*) FROM [Conversation] 
     WHERE ToUserId = 'user1' AND FromUserId = U.UserId) 'ReceivedCount'
FROM 
    [Conversation] C 
INNER JOIN 
    [User] U ON U.UserId = C.FromUserId
WHERE 
    C.ToUserId = 'user1'

查询返回一个结果,但它不包括某些行。 Conversation 表包含相同的FromUserId(发送消息用户)和ToUserId(接收消息用户)。

这是表格:

当前结果-

预期结果:

带有虚拟数据的表 -

CREATE TABLE [dbo].[User](
    [Id] [int] NULL,
    [UserId] [varchar](5) NULL,
    [Name] [varchar](5) NULL,
    [Email] [varchar](11) NULL
) ON [PRIMARY]

INSERT [dbo].[User] ([Id], [UserId], [Name], [Email]) VALUES (1, N'user1', N'user1', N'user1@a.com')
INSERT [dbo].[User] ([Id], [UserId], [Name], [Email]) VALUES (2, N'user2', N'user2', N'user2@a.com')
INSERT [dbo].[User] ([Id], [UserId], [Name], [Email]) VALUES (3, N'user3', N'user3', N'user3@a.com')
INSERT [dbo].[User] ([Id], [UserId], [Name], [Email]) VALUES (4, N'user4', N'user4', N'user4@a.com')
INSERT [dbo].[User] ([Id], [UserId], [Name], [Email]) VALUES (5, N'user5', N'user5', N'user5@a.com')

CREATE TABLE [dbo].[Conversation](
    [Id] [int] NULL,
    [conversationId] [varchar](14) NULL,
    [messageId] [varchar](4) NULL,
    [fromUserId] [varchar](5) NULL,
    [toUserId] [varchar](5) NULL
) ON [PRIMARY]

INSERT [dbo].[Conversation] ([Id], [conversationId], [messageId], [fromUserId], [toUserId]) VALUES (1, N'con-user1user2', N'mes1', N'user1', N'user2')
INSERT [dbo].[Conversation] ([Id], [conversationId], [messageId], [fromUserId], [toUserId]) VALUES (2, N'con-user1user2', N'mes2', N'user1', N'user2')
INSERT [dbo].[Conversation] ([Id], [conversationId], [messageId], [fromUserId], [toUserId]) VALUES (3, N'con-user2user1', N'mes3', N'user2', N'user1')
INSERT [dbo].[Conversation] ([Id], [conversationId], [messageId], [fromUserId], [toUserId]) VALUES (4, N'con-user1user3', N'mes4', N'user1', N'user3')
INSERT [dbo].[Conversation] ([Id], [conversationId], [messageId], [fromUserId], [toUserId]) VALUES (5, N'con-user4user1', N'mes5', N'user4', N'user1')

有人可以帮助如何包含所有记录吗?

谢谢!

【问题讨论】:

  • 请提供重现问题的表结构和示例数据(例如,向我们展示您认为应该包含但未包含的行)。你可以这样做at db<>fiddle
  • 一个DISTINCT 和一个GROUP BY 在不包含聚合的查询中(子查询中的聚合在不同的范围内)表明这里有问题。在同一个查询中拥有GROUP BYDISTINCT 通常意味着您的GROUP BY 是错误的(因为GROUP BY 应该已经返回不同组的行),并且带有GROUP BY 且没有聚合的查询通常意味着不需要GROUP BY
  • @AaronBertrand 更新了表结构
  • Conversation.FromUserId 和 Conversation.ToUserId 上是否有外键?
  • @DavidBrowne-Microsoft 没有

标签: sql sql-server sql-server-2008


【解决方案1】:

外部查询中不需要join。这将更简单地写为:

SELECT U.UserId as Id, U.FullName as Name,
    (SELECT COUNT(*)
     FROM [Conversation] c
     WHERE c.FromUserId = 'user1' AND c.ToUserId = U.UserId
    ) as SentCount,
    (SELECT COUNT(*)
     FROM [Conversation] c 
     WHERE c.ToUserId = 'user1' AND c.FromUserId = U.UserId
    ) as ReceivedCount
FROM [User] U ;

注意事项:

  • 限定所有列引用。这对于关联子句尤为重要。
  • 提供作为表名缩写的表别名。
  • 仅对字符串和日期常量使用单引号。不要使用 for 列别名。

Here 是一个 dbfiddle。

【讨论】:

  • 我需要 where 条件来选择特定用户,上面的查询让我发送/接收计数为零
  • @NileshMistry 再来一次:请提供样本数据以及您想要的结果。
  • @NileshMistry 。 . .您想要的结果显示所有用户的行。
  • @AaronBertrand 我已经用脚本生成了测试数据。怎么给你?
  • @NileshMistry 。 . .这个答案可以满足您的要求。我包括了一个 dbfiddle.
【解决方案2】:

您的基本选择不需要对话表。像这样可以工作,但可以使用子查询进行优化:


Select U.UserId as 'Id', 
 U.name as 'Name',
 isnull(fromSummed.sentCount, 0) 'SentCount',
 isnull(ToSummed.ReceivedCount, 0) 'ReceivedCount'
FROM [User] U 
outer apply (select count(*) as sentCount from [Conversation] cFrom where cFrom.FromUserId = 'user1' and ToUserId = U.UserId ) fromSummed
outer apply (select count(*) as ReceivedCount from [Conversation] cTo where cTo.ToUserId = 'user1' and cTo.FromUserId = U.UserId) ToSummed
where isnull(fromSummed.sentCount, 0)>0 or isnull(ToSummed.ReceivedCount, 0)>0

【讨论】:

  • 此选择将通过您数据库中的所有用户并检查“user1”是否向他/她发送了消息。您可以添加 where 子句以排除发送和接收均为 null 或 0 的行。
  • 因语法错误而无法工作。我正在使用 ms sql 2008。是因为这个吗?
  • @NileshMistry 如果您使用的是不受支持的 SQL Server 版本,请始终预先指定。如果没有这些细节,普遍的假设是您使用的是最近十年的软件。
  • @AaronBertrand 好的
  • 我更正了查询。我需要这些表来测试编译。请现在检查。它是 2008 兼容的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
相关资源
最近更新 更多