2

我有一个看似常见的业务请求,但我找不到明确的解决方案。我有一份每日报告(其中有很多),它根据失败的标准生成并保存到表格中。每个报告都有一个与之关联的类型 ID 以表示它是哪个报告,并且有一个导入事件 ID 表示导入的日期(添加日期列以进行额外说明)。我添加了一个 sqlfiddle 来查看表的基本架构(因隐私问题而重命名)。

http://www.sqlfiddle.com/#!3/81945/8

当前生成的所有报告都工作正常,因此无需在表格上进行任何修改。但是,对于一份报告(类型 11),我不仅需要提取今天显示的发票,还需要添加一列,该列总计从该发票运行之日起连续天数(包括当天)。根据提供的架构,结果应如下所示:

INVOICE     MESSAGE     EVENT_DATE      CONSECUTIVE_DAYS_ON_REPORT
12345       Yes         July, 30 2013    6
54355       Yes         July, 30 2013    2
644644      Yes         July, 30 2013    4

我只需要最近的连续天数,而不需要任何其他可能出现的集合。我试图运行自我连接无济于事,我的最后一次尝试也被列为 sqlfiddle 文件的一部分,但无济于事。有什么建议或想法吗?我现在很困。

仅供参考: 我在 SQL Server 2000 中工作! 我看到了很多在 2005 年和 2008 年出现的巧妙技巧,但我无法访问它们。

非常感谢您的帮助!

4

3 回答 3

0

不久前,我有一个类似的要求,获得“前 5 名”排名,连续数个时段进入前 5 名。我找到的唯一解决方案是在游标中进行。date = @daybefore如果您的数据不匹配,则光标在光标内有一个and 退出循环,否则设置@daybefore = datediff(dd, -1, @daybefore)。

如果你想要一个例子,请告诉我。似乎有很多爱好者,即使他们没有更好的解决方案,当他们看到“光标”这个词时也会投反对票......

在这里,尝试这样的标量函数:

CREATE FUNCTION ConsequtiveDays
(
    @invoice bigint, @date datetime
)
RETURNS int
AS
BEGIN
    DECLARE @ct int = 0, @Count_Date datetime, @Last_Date datetime

    SELECT @Last_Date = @date

    DECLARE counter CURSOR LOCAL FAST_FORWARD
    FOR
    SELECT event_date FROM tblEventInfo 
    WHERE invoice = @invoice
    ORDER BY event_date DESC

    FETCH NEXT FROM counter
    INTO @Count_Date

    WHILE @@FETCH_STATUS = 0 AND DATEDIFF(dd,@Last_Date,@Count_Date) < 2
    BEGIN
        @ct = @ct + 1
    END

    CLOSE counter
    DEALLOCATE counter

    RETURN @ct

END
GO
于 2013-07-30T19:28:34.147 回答
0

像这样的东西? http://www.sqlfiddle.com/#!3/81945/14

SELECT
  [final].*,
  [last].total_rows
FROM
  tblEventInfo   AS [final]
INNER JOIN
(
  SELECT
    [first_of_last].type_id,
    [first_of_last].invoice,
    MAX([all_of_last].event_date)   AS event_date,
    COUNT(*)                        AS total_rows
  FROM
  (
    SELECT
      [current].type_id,
      [current].invoice,
      MAX([current].event_date)   AS event_date
    FROM
      tblEventInfo   AS [current]
    LEFT JOIN
      tblEventInfo   AS [previous]
        ON  [previous].type_id    = [current].type_id
        AND [previous].invoice    = [current].invoice
        AND [previous].event_date = [current].event_date-1
    WHERE
          [current].type_id = 11
      AND [previous].type_id IS NULL
    GROUP BY
      [current].type_id,
      [current].invoice
  )
    AS [first_of_last]
  INNER JOIN
    tblEventInfo  AS [all_of_last]
      ON  [all_of_last].type_id     = [first_of_last].type_id
      AND [all_of_last].invoice     = [first_of_last].invoice
      AND [all_of_last].event_date >= [first_of_last].event_date
  GROUP BY
    [first_of_last].type_id,
    [first_of_last].invoice
)
  AS [last]
    ON  [last].type_id    = [final].type_id
    AND [last].invoice    = [final].invoice
    AND [last].event_date = [final].event_date

最内层查询查找最后一个连续记录块的起始记录。

然后连接到该连续记录块中的所有记录,给出最终日期和行数(连续天数)

然后加入最后一天的行以获取消息等。


确保实际上您有一个关于(type_id, invoice, event_date).

于 2013-07-30T19:55:43.423 回答
0

你有多个问题。分别处理它们并建立起来。

问题:

1)识别连续范围:从范围列中减去row_number并按结果分组

2) SQL 2000 中没有 ROW_NUMBER() 函数:用相关子查询伪造它。

3)您实际上想要 DENSE_RANK() 而不是 ROW_NUMBER:首先列出唯一日期。

解决方案:

3)

SELECT MAX(id) AS id,invoice,event_date FROM tblEventInfo GROUP BY invoice,event_date

2)

  SELECT t2.invoice,t2.event_date,t2.id,
    DATEDIFF(day,(SELECT COUNT(DISTINCT event_date) FROM (SELECT MAX(id) AS id,invoice,event_date FROM tblEventInfo GROUP BY invoice,event_date) t1 WHERE t2.invoice = t1.invoice AND t2.event_date > t1.event_date),t2.event_date) grp
  FROM (SELECT MAX(id) AS id,invoice,event_date FROM tblEventInfo GROUP BY invoice,event_date) t2
  ORDER BY invoice,grp,event_date

1)

SELECT
  t3.invoice AS INVOICE,
  MAX(t3.event_date) AS EVENT_DATE,
  COUNT(t3.event_date) AS CONSECUTIVE_DAYS_ON_REPORT
FROM (
  SELECT t2.invoice,t2.event_date,t2.id,
    DATEDIFF(day,(SELECT COUNT(DISTINCT event_date) FROM (SELECT MAX(id) AS id,invoice,event_date FROM tblEventInfo GROUP BY invoice,event_date) t1 WHERE t2.invoice = t1.invoice AND t2.id > t1.id),t2.event_date) grp
  FROM (SELECT MAX(id) AS id,invoice,event_date FROM tblEventInfo GROUP BY invoice,event_date) t2
) t3
GROUP BY t3.invoice,t3.grp

你剩下的问题有点模棱两可。如果两个范围的长度相等,您想要两个范围还是只需要最近的范围?如果任何消息 = 'Yes' 或仅当最近的消息 = 'Yes' 时,输出 MESSAGE 是否应该为 'Yes'?

不过,这应该给你足够的面包屑

于 2013-07-30T20:36:24.353 回答