SQL查询:一个存储过程,用于接收用户ProfileId并获取联系人列表中的表消息
我需要一个复杂的select查询的帮助。我有一个消息表SQL查询:一个存储过程,用于接收用户ProfileId并获取联系人列表中的表消息,sql,sql-server-2008,Sql,Sql Server 2008,我需要一个复杂的select查询的帮助。我有一个消息表 CREATE TABLE Message( MessageId int IDENTITY(1,1) NOT NULL, /*primary key*/ FromProfileId int NOT NULL, /*foreign key to Profile table*/ ToProfileId int NOT NULL, /*foreign key to Profile table*/ Datetime d
CREATE TABLE Message(
MessageId int IDENTITY(1,1) NOT NULL, /*primary key*/
FromProfileId int NOT NULL, /*foreign key to Profile table*/
ToProfileId int NOT NULL, /*foreign key to Profile table*/
Datetime datetime NOT NULL,
MessageText ntext NOT NULL,
IsNew bit NOT NULL )
我需要一个存储过程来接收用户ProfileId并获取联系人列表中的表消息,如下所示:
(ContactProfileId
用户已发送或已接收消息)ProfileId
(所有发送/接收的邮件都计入联系人档案ID)allmessagescont
(从newmessagescont
收到的新邮件计数)ContactProfileId
(LastMessageDateTime from/toLastMessageDateTime
)ContactProfileId
- 一些
配置文件信息从配置文件表中加入李>ContactProfileId
已更新:以下是一些数据的示例
MessageId FromProfileId ToProfileId messageDatetime IsNew
--------------------------------------------------------------------
1 2 3 2010-11-20 18:16:40.230 1
2 2 3 2010-12-20 18:16:40.230 1
3 3 2 2010-10-20 18:16:40.230 0
4 3 4 2010-12-25 18:16:40.230 1
参数ProfileId=3时SP的结果必须为
ContactProfileId AllMessagesCount NewMessagesCount LastMessageDateTime ContactName
---------------------------------------------------------------------------------------------------------------------
2 3 2 2010-12-20 18:16:40.230 Contact Name joined from Profile Table
4 1 0 2010-12-25 18:16:40.230 Contact Name joined from Profile Table
您不太清楚要获取什么,以及如何获取-您希望将值作为存储过程的输出参数,还是作为输出结果集获取 此外,您的需求列表中的第一点和最后一点非常模糊。。。。你能详细说明一下吗??看起来好像你想要个人资料ID的列表-对吗 这是第一次尝试:
CREATE PROCEDURE dbo.DoSomething @ProfileID INT
AS BEGIN
DECLARE @AllMsgCount INT, @NewMsgCount INT
DECLARE @LastMsgDate DATETIME
-- count all messages
SELECT @AllMsgCount = COUNT(*)
FROM dbo.[Message]
WHERE (FromProfileId = @ProfileID OR ToProfileId = @ProfileID)
-- count new messages
SELECT @NewMsgCount = COUNT(*)
FROM dbo.[Message]
WHERE FromProfileId = @ProfileID
AND IsNew = 1
-- determine last datetime
SELECT @LastMsgDate = MAX([Datetime])
FROM dbo.[Message]
WHERE (FromProfileId = @ProfileID OR ToProfileId = @ProfileID)
-- return three values as a result set
SELECT @AllMsgCount, @NewMsgCount, @LastDateTime
-- ProfileId that user has sent message to or has received message from
-- select all profile ID's where the user has sent a message to, or
-- received a message from; return as a second result set
SELECT DISTINCT ToProfileId
FROM dbo.[Message]
WHERE FromProfileId = @ProfileID
UNION ALL
SELECT DISTINCT FromProfileId
FROM dbo.[Message]
WHERE ToProfileId = @ProfileID
-- return from profile data from the profile table
SELECT (list of columns)
FROM dbo.Profile
WHERE ProfileId = @ProfileID
END
另外:您可能希望为DATETIME
列找到一个比DATETIME
更聪明的名称。。。。。这同样适用于消息
,它也是SQL Server保留字,不应作为列名使用
此外:基于单一责任原则,我认为使用单一存储过程从不同位置返回各种不同数据是一种糟糕的体系结构。我建议存储一个进程,每个进程返回一组数据,如果您需要三组数据,请使用三个过程。。。。。让维护变得简单多了
更新:我的第二次尝试,利用Richard提供的一些输入:我正在使用CTE(公共表表达式)获取您可能感兴趣的数据。不过:我相信您提供的样本数据有错误-请检查
CREATE PROCEDURE dbo.DoSomething @ProfileID INT
AS
-- this CTE finds all distinct ProfileID's that the one passed in
-- as a parameter has had message exchange with
;WITH Contacts AS
(
SELECT DISTINCT ToProfileID AS 'ProfileID'
FROM dbo.Messages
WHERE FromProfileId = @ProfileID
UNION
SELECT DISTINCT FromProfileID AS 'ProfileID'
FROM dbo.Messages
WHERE ToProfileId = @ProfileID
)
SELECT
c.ProfileID,
COUNT(*) AS AllMessagesCount,
COUNT(CASE WHEN IsNEW = 1 AND FromProfileID IS NOT NULL THEN 1 ELSE NULL END) AS NewMessagesCount,
MAX(Datetime) AS LastMessageDateTime,
p.ContactName
FROM
Contacts c -- our CTE with the communication partners
INNER JOIN
Messages m ON (m.FromProfileId = c.ProfileID OR m.ToProfileId = c.ProfileID)
INNER JOIN
dbo.profiles p ON c.ProfileID = p.ProfileID
GROUP BY
c.ProfileID, p.ContactName
这将产生类似这样的输出(我冒昧地将一些示例ContactName
添加到Profiles
表中):
您不太清楚要获取什么,以及如何获取-您希望将值作为存储过程的输出参数,还是作为输出结果集获取 此外,您的需求列表中的第一点和最后一点非常模糊。。。。你能详细说明一下吗??看起来好像你想要个人资料ID的列表-对吗 这是第一次尝试:
CREATE PROCEDURE dbo.DoSomething @ProfileID INT
AS BEGIN
DECLARE @AllMsgCount INT, @NewMsgCount INT
DECLARE @LastMsgDate DATETIME
-- count all messages
SELECT @AllMsgCount = COUNT(*)
FROM dbo.[Message]
WHERE (FromProfileId = @ProfileID OR ToProfileId = @ProfileID)
-- count new messages
SELECT @NewMsgCount = COUNT(*)
FROM dbo.[Message]
WHERE FromProfileId = @ProfileID
AND IsNew = 1
-- determine last datetime
SELECT @LastMsgDate = MAX([Datetime])
FROM dbo.[Message]
WHERE (FromProfileId = @ProfileID OR ToProfileId = @ProfileID)
-- return three values as a result set
SELECT @AllMsgCount, @NewMsgCount, @LastDateTime
-- ProfileId that user has sent message to or has received message from
-- select all profile ID's where the user has sent a message to, or
-- received a message from; return as a second result set
SELECT DISTINCT ToProfileId
FROM dbo.[Message]
WHERE FromProfileId = @ProfileID
UNION ALL
SELECT DISTINCT FromProfileId
FROM dbo.[Message]
WHERE ToProfileId = @ProfileID
-- return from profile data from the profile table
SELECT (list of columns)
FROM dbo.Profile
WHERE ProfileId = @ProfileID
END
另外:您可能希望为DATETIME
列找到一个比DATETIME
更聪明的名称。。。。。这同样适用于消息
,它也是SQL Server保留字,不应作为列名使用
此外:基于单一责任原则,我认为使用单一存储过程从不同位置返回各种不同数据是一种糟糕的体系结构。我建议存储一个进程,每个进程返回一组数据,如果您需要三组数据,请使用三个过程。。。。。让维护变得简单多了
更新:我的第二次尝试,利用Richard提供的一些输入:我正在使用CTE(公共表表达式)获取您可能感兴趣的数据。不过:我相信您提供的样本数据有错误-请检查
CREATE PROCEDURE dbo.DoSomething @ProfileID INT
AS
-- this CTE finds all distinct ProfileID's that the one passed in
-- as a parameter has had message exchange with
;WITH Contacts AS
(
SELECT DISTINCT ToProfileID AS 'ProfileID'
FROM dbo.Messages
WHERE FromProfileId = @ProfileID
UNION
SELECT DISTINCT FromProfileID AS 'ProfileID'
FROM dbo.Messages
WHERE ToProfileId = @ProfileID
)
SELECT
c.ProfileID,
COUNT(*) AS AllMessagesCount,
COUNT(CASE WHEN IsNEW = 1 AND FromProfileID IS NOT NULL THEN 1 ELSE NULL END) AS NewMessagesCount,
MAX(Datetime) AS LastMessageDateTime,
p.ContactName
FROM
Contacts c -- our CTE with the communication partners
INNER JOIN
Messages m ON (m.FromProfileId = c.ProfileID OR m.ToProfileId = c.ProfileID)
INNER JOIN
dbo.profiles p ON c.ProfileID = p.ProfileID
GROUP BY
c.ProfileID, p.ContactName
这将产生类似这样的输出(我冒昧地将一些示例ContactName
添加到Profiles
表中):
或者,使用CTE:
WITH filteredmessages AS (
SELECT
ContactProfileId =
CASE ToProfileId
WHEN @ProfileId THEN FromProfileId
ELSE ToProfileId
END)
messageDateTime,
IsNew
FROM Message
WHERE @ProfileId IN (FromProfileId, ToProfileId)
),
groupedmessages AS (
SELECT
ContactProfileId,
AllMessagesCount = COUNT(*),
NewMessagesCount = COUNT(CASE IsNew WHEN 1 THEN 1 END),
LastMessageDateTime = MAX(messageDateTime)
FROM filteredmessages
GROUP BY ContactProfileId
)
SELECT m.*, p.Name AS ContactName
FROM groupedmessages m
INNER JOIN Profile p ON m.ContactProfileId = p.Id
或者,使用CTE:
WITH filteredmessages AS (
SELECT
ContactProfileId =
CASE ToProfileId
WHEN @ProfileId THEN FromProfileId
ELSE ToProfileId
END)
messageDateTime,
IsNew
FROM Message
WHERE @ProfileId IN (FromProfileId, ToProfileId)
),
groupedmessages AS (
SELECT
ContactProfileId,
AllMessagesCount = COUNT(*),
NewMessagesCount = COUNT(CASE IsNew WHEN 1 THEN 1 END),
LastMessageDateTime = MAX(messageDateTime)
FROM filteredmessages
GROUP BY ContactProfileId
)
SELECT m.*, p.Name AS ContactName
FROM groupedmessages m
INNER JOIN Profile p ON m.ContactProfileId = p.Id
你能给我们看看你已经有了什么吗??另外:停止使用
NTEXT
-自SQL Server 2005以来,它已被弃用-改用NVARCHAR(MAX)
,更易于使用。您是否可以构建一个SELECT来满足您的要求?还有,您需要存储过程的具体原因是什么?提示,SELECT和SP几乎是一样的。谢谢你的建议。我几乎什么都没有,我无法想象我该怎么做。问题是SELECT not SP。@marc_s:这是profileid=4的新消息,但不是profileid=3。新消息可以是接收到用户的消息(在本例中,profileid=3用户),当ToProfileId=@pofileid时,您可以向我们展示您已经拥有的吗??另外:停止使用NTEXT
-自SQL Server 2005以来,它已被弃用-改用NVARCHAR(MAX)
,更易于使用。您是否可以构建一个SELECT来满足您的要求?还有,您需要存储过程的具体原因是什么?提示,SELECT和SP几乎是一样的。谢谢你的建议。我几乎什么都没有,我无法想象我该怎么做。问题是SELECT not SP。@marc_s:这是profileid=4的新消息,但不是profileid=3。新消息可以是接收到用户的消息(在本例中,profileid=3用户),这就是托吡酯的作用=@PofileId@marc_s:谢谢。编辑。我想我一次就搞定了。也许我错了?@marc\s:谢谢。编辑。我想我一次就搞定了。也许我错了?马克,整晚都在烦我。马克,整晚都在烦我。但是你的输出也显示了newmessagescont=1
的ContactProfileId=4
-就像我的一样。。。这是错误的,根据OP@marc_s:真的!我只是浏览了OP的输出示例,一开始并没有注意到不一致性。但是您的输出还显示了ContactProfileId=4的newmessagescont=1
——就像我的一样。。。这是错误的,根据OP@marc_s:真的!我只浏览了OP的输出示例,一开始并没有注意到不一致性。