【问题标题】:SQL Server - Refactor Large Union QuerySQL Server - 重构大型联合查询
【发布时间】:2026-01-27 19:25:01
【问题描述】:

我有以下表格:

CREATE TABLE Forms (
    ID int NOT NULL PRIMARY KEY,
    FormName varchar
);

INSERT INTO Forms (ID, FormName)
VALUES (1, 'Password_Reset_Form'), (2, 'Service_Request_Form');

 CREATE TABLE Cases (
    ID int NOT NULL PRIMARY KEY,
    CreatedDt datetime       
 );

 INSERT INTO Cases (ID, CreatedDt)
 VALUES (1, '2018-05-8'), (2, '2018-05-9'), (3, '2018-05-10');

 CREATE TABLE Password_Reset_Form (
    ID int NOT NULL PRIMARY KEY,
    CaseID int FOREIGN KEY REFERENCES Cases(ID),
    Subject varchar,
    FormName varchar FOREIGN KEY REFERENCES Forms(FormName)
 );

 INSERT INTO Password_Reset_Form (ID, CaseID, Subject, FormName)
 VALUES (1, 1, 'Password Issue', 'Password_Reset_Form');


 CREATE TABLE Service_Request_Form (
    ID int NOT NULL PRIMARY KEY,
    CaseID int FOREIGN KEY REFERENCES Cases(ID),
    Subject varchar,
    FormName varchar FOREIGN KEY REFERENCES Forms(FormName)
 );  

 INSERT INTO Service_Request_Form (ID, CaseID, Subject, FormName)
 VALUES (1, 2, 'Add User', 'Service_Request_Form'), (1, 3, 'Delete User', 'Service_Request_Form'); 

当提交每种类型的表单时,Cases 表中会记录一个新案例,并将所有表单数据记录在相应的表单表中,例如在上述情况下,Password_Reset_Form 表或 Service_Request_Form 表。我有超过 400 个此类表单表,除了 CaseIDSubjectFormName 字段之外,每个表都可以包含不同的字段。

我想列出所有表格以及在特定日期之间为每个表格提出的案件数量。

我可以执行以下操作,但我必须合并 100 个表

SELECT t2.FormName, COUNT(1) as TotalCases
FROM Cases t1
INNER JOIN (
   select CaseID, FormName FROM Password_Reset_Form
   union all 
   select CaseID, FormName FROM Service_Request_Form
   /* 400 + more unions */ ) t2
WHERE t1.CreatedDt BETWEEN '2018-05-08' AND '2018-05-10'
GROUP BY t2.FormName

有没有办法可以使用 Form 表,因为它已经有一个表单名称列表来简化查询,即使用该表中的 FormName 值作为联合查询中的表名或其他什么?

* 请注意,我无法更改设计,因为它是专有数据库 *

【问题讨论】:

  • 可能不会。表格有可用的表格,但没有关于谁拿它以及何时拿它的详细信息。这是糟糕的设计。一旦喜欢 10 个不同的表格,这个设计怎么不被重构??
  • 问题在于你的设计。您应该在 RequestForm 表中有一个列来指示 FormType 而不是 100 个表。
  • 不能改变数据库的事实并不能改变设计是问题的事实。太糟糕了。我会考虑创建一个视图以从所有这些相同的表中返回 CaseID 和 FormName。呃,我不羡慕你在做这个,多么皇家的 PITA !!!
  • 编写一次代码并通过作业/ssis 包每天几次插入到自定义表中?

标签: sql-server union


【解决方案1】:

是的,您可以使用表格。但是,如果您想避免大型 UNION 查询,则需要进行一些其他额外的结构更改。

所以这取决于当前数据库结构的灵活性。您是否允许更改数据库中的表结构?如果是这样,我将为表单创建一个表而不是多个表。假设这个表将被称为 FormCases。它看起来像这样:

CREATE TABLE FormCases (
    ID int NOT NULL PRIMARY KEY,
    FormID int FOREIGN KEY REFERENCES Forms(ID),
    CaseID int FOREIGN KEY REFERENCES Cases(ID),
    Subject varchar
);

INSERT INTO FormCases (ID, FormID, CaseID, Subject)
VALUES
    (1, 1, 1, 'Password Issue'),
    (1, 2, 2, 'Add User'),
    (1, 2, 3, 'Delete User');

编辑:刚刚看到您无法更改数据库。那么你运气不好,你确实需要使用大型 UNION 查询。对不起。

【讨论】: