Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL查询:一个存储过程,用于接收用户ProfileId并获取联系人列表中的表消息_Sql_Sql Server 2008 - Fatal编程技术网

SQL查询:一个存储过程,用于接收用户ProfileId并获取联系人列表中的表消息

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

我需要一个复杂的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 datetime NOT NULL,
    MessageText ntext NOT NULL,
    IsNew bit NOT NULL )
我需要一个存储过程来接收用户ProfileId并获取联系人列表中的表消息,如下所示:

  • ContactProfileId
    ProfileId
    用户已发送或已接收消息)
  • allmessagescont
    (所有发送/接收的邮件都计入联系人档案ID)
  • newmessagescont
    (从
    ContactProfileId
    收到的新邮件计数)
  • LastMessageDateTime
    (LastMessageDateTime from/to
    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的输出示例,一开始并没有注意到不一致性。