【问题标题】:SQL Server: How to limit stored procedure to only show one (next) matching recordSQL Server:如何限制存储过程只显示一个(下一个)匹配记录
【发布时间】:2014-02-18 12:16:57
【问题描述】:

我正在使用以下存储过程从数据库中获取一些数据。 meetingDate 列的格式为日期时间,并且仅包含有效数据。

如何修改存储过程,使其只显示下一条匹配记录而不是全部?

示例:

今天 = 2014 年 2 月 18 日; 数据库包含 meetingDate = 20/02/2014、27/02/2014 和 04/03/2014 的记录; 在这种情况下,结果应该只是 20/02/2014 的记录,作为未来的下一个匹配记录。

我的存储过程:

ALTER PROCEDURE [dbo].[FetchMeetings]
AS
BEGIN
    SET NOCOUNT ON;
    SELECT      A.meetingID,
                CONVERT(VARCHAR(11), A.meetingDate, 106) AS meetingDate,
                A.created,
                A.createdBy,
                A.updated,
                A.updatedBy,
                B.speaker AS speaker,
                B.topic AS topic
    FROM        MeetingDates A
    INNER JOIN  MeetingDetails B
    ON          A.meetingID = B.meetingID
    WHERE       meetingDate >= GETDATE()
    ORDER BY    meetingDate, speaker, topic
    FOR XML PATH('meeting'), ELEMENTS, TYPE, ROOT('ranks')
END

非常感谢您提供的任何帮助,蒂姆。

【问题讨论】:

  • 可能是日期列格式不同。日期列的数据类型和日期参数数据类型是什么?

标签: sql sql-server datetime stored-procedures


【解决方案1】:

使用 SELECT TOP 1

SELECT      A.meetingID,
            CONVERT(VARCHAR(11), A.meetingDate, 106) AS meetingDate,
            A.createdBy,
            B.speaker AS speaker,
            B.topic AS topic
            FROM MeetingDates A
INNER JOIN  MeetingDetails B
ON          A.meetingID = B.meetingID
            WHERE a.meetingDate IN (
SELECT      TOP 1(a.meetingDate)
FROM        MeetingDates A
WHERE       meetingDate >= GETDATE()
ORDER BY    meetingDate ASC)
ORDER BY    speaker, topic
FOR XML PATH('meeting'), ELEMENTS, TYPE, ROOT('ranks')

【讨论】:

  • 我刚刚看到这弄乱了 JOIN,然后也只从那里返回第一条记录,但这里我需要所有匹配的记录。
  • 它搞砸了连接是什么意思?查询到底应该显示什么?是不是一次会议有很多会议细节?它实际上显示了什么?
  • 感谢您的快速帮助(对不起,这在我之前的评论中被意外删除了)。对于所有 A. 项目,Top 1 是完美的,因为我只需要下一次会议,但一次会议可以在 B. 表上有多个主题,所以我需要所有匹配的项目。
  • 查看我的答案的修正,这似乎给了你想要的东西。我已经用一个基本的测试数据库试过了。
【解决方案2】:

使用窗口函数。它兼容 sql server 2005+

这是我的数据示例

with p as (
 select *, dense_RANK() over (order by foryear desc, formonth desc) as rnk 
from RISK_TRANS.dbo.mytable
) 

select * from p
where rnk = 2

我的钥匙是 2014 - 1 和 2013-12; 2013 年 11 月。它只会像你期望的那样选择我 2013-12

你能试试这个吗:(我不确定语法是否正确,我只是做了更改,没有运行)

ALTER PROCEDURE [dbo].[FetchMeetings]
AS
BEGIN
    SET NOCOUNT ON;
    with p as (
    SELECT A.meetingID,
                CONVERT(VARCHAR(11), A.meetingDate, 106) AS meetingDate,
                A.created,
                A.createdBy,
                A.updated,
                A.updatedBy,
                B.speaker AS speaker,
                B.topic AS topic,
                DENSE_RANK() over (order by CONVERT(VARCHAR(11), A.meetingDate, 106) desc) rnk
    FROM        MeetingDates A
    INNER JOIN  MeetingDetails B
    ON          A.meetingID = B.meetingID
    WHERE       meetingDate >= GETDATE())

    select meetingid, meetingdate, createddate, createdby, updated, updatedby, speaker, topic 
    from p
    ORDER BY    meetingDate, speaker, topic
    FOR XML PATH('meeting'), ELEMENTS, TYPE, ROOT('ranks')
END

【讨论】:

  • 谢谢! - 我收到 DENSE_RANK 行的错误:Msg 156, Level 15, State 1, Procedure FetchMeetings, Line 25 关键字“OVER”附近的语法不正确。
  • 是的,抱歉忘记了 dense_rank 之后的括号 :) 就像我说我对语法没有 100% 的信心
  • 非常感谢 - 这似乎也有效。我现在正在对此进行更多测试。
【解决方案3】:

尝试使用 SELECT 1 构造,检查这里1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 2013-03-26
    • 2012-02-10
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多