首页 > 解决方案 > SQL 为每个额外计数创建一个重复行

问题描述

我有一个具有多对多关系的表,我需要在不修改架构的情况下进行 1 对 1。这是伪代码:

 Reports  { 
      Id INT,  
      Description NVARCHAR(256),
      ReportFields...  
 }
 ScheduledReports { 
    ScheduledReportId INT
    ReportId INT (FK)
    Frequency INT
 }

当我运行此查询时:

SELECT [ReportID], COUNT(*) as NumberOfReports
FROM [ScheduledReports]
GROUP BY ReportId
HAVING COUNT(*) > 1

我会返回所有有重复的报告的结果。

ReportId,  NumberOfReports
   1,         2
   2,         4

Foreach 附加报告(例如 NumberOfReports -1)。
我需要在 Reports 表中创建一个重复的行。但是我在弄清楚如何将计数转换为连接时遇到了麻烦(因为我不想使用游标)。

这是我的查询:

INSERT INTO Reports (Description)
SELECT Description 
FROM Reports 
WHERE ReportId IN  (SELECT [ReportID]
                    FROM [ScheduledReports]
                    GROUP BY ReportId
                    HAVING COUNT(*) > 1)

如何将 ReportRow 自身加入 Count(*) -1 次?

标签: sqljoincartesian-product

解决方案


下面的查询应该为您提供每个唯一报告的时间表排序。然后,您可以使用sequencing > 1来确定需要将哪些值插入到您的报告表中。这个选择的输出可能应该被缓存,因为它会

  1. 通过当前 ID 指示需要将哪些行添加到您的报告中
  2. 可用于稍后更新计划表中引用的 ReportID
SELECT * 
FROM (
    SELECT Reports.Id
        ,ScheduledReportId
        ,ROW_NUMBER() OVER (
            PARTITION BY ReportId
            ORDER BY ScheduledReportId
        ) AS [Sequencing]
    FROM Reports 
        INNER JOIN ScheduledReports on ScheduledReports.ReportId = Reports.Id
    WHERE ReportId IN  (SELECT [ReportID]
                        FROM [ScheduledReports]
                        GROUP BY ReportId
                        HAVING COUNT(*) > 1)) AS SequencedReportAndSchedules

推荐阅读