我有一个包含Type,ID(pk)和Name列的表模板。 这些模板可以应用于两个不同的表,Person和Role。 用户可以创建自己的模板,但这些模板始终是预定义的类型。
我编写的代码用于检查当前现有模板的使用级别,但添加检查可能在将来创建的模板的功能超出了我当前的能力。
SELECT t.Name As [Template Name],
CASE
WHEN t.Type = 5 THEN SUM(CASE WHEN p.tID BETWEEN 2 AND 3 THEN 1 ELSE 0 END)
WHEN t.TYPE = 10 THEN SUM(CASE WHEN r.tID BETWEEN 4 AND 5 THEN 1 ELSE 0 END)
WHEN t.TYPE = 100 THEN SUM(CASE WHEN p.tID = 8 THEN 1 ELSE 0 END)
WHEN t.TYPE = 20 THEN SUM(CASE WHEN r.tID BETWEEN 6 AND 7 THEN 1 ELSE 0 END)
WHEN t.TYPE = 3 THEN SUM(CASE WHEN r.tID BETWEEN 9 AND 10 THEN 1 ELSE 0 END)
END As [Times Used],
t.ID As [Template ID], t.Type As [Template Type]
FROM Templates t, Person p, Role r
GROUP BY t.Name, t.ID, t,Type
ORDER BY [Times Used] ASC, t.Type, t.Name, t.ID
......以上五种类型是不变的。如上所述,我希望代码能够检查将来可能添加的其他模板,但不知道如何执行此操作。
一如既往,感激不尽的任何帮助。
使用的是SQL Server 2012。
中号
P.S。就像这里给大家的快速记录一样,我继承了这个数据库,我无法控制现有的数据结构。我正在努力为未来证明这一点,尽我所能。“
为了澄清,Template.Type值永远不会改变。但是,用户可以在将来的任何时候创建一个新模板(模板只能应用于Person或Role,而不是两者),这将是以上五种类型中的一种。
对于Template.Type,值为5& 100表示模板适用于Person。值10,20和& 3表示它是一个角色。因此,在这些情况下,只需要分别搜索Person和Role表。
我的代码目前搜索所有现有的Template.ID值,但我不确定如何添加功能来搜索将来可能创建的ID值。
答案 0 :(得分:0)
您可以在ELSE
语句中添加CASE
子句,该子句可以捕获任何未计入的内容:
CASE
WHEN t.Type = 5 THEN SUM(CASE WHEN p.tID BETWEEN 2 AND 3 THEN 1 ELSE 0 END)
WHEN t.TYPE = 10 THEN SUM(CASE WHEN r.tID BETWEEN 4 AND 5 THEN 1 ELSE 0 END)
WHEN t.TYPE = 100 THEN SUM(CASE WHEN p.tID = 8 THEN 1 ELSE 0 END)
WHEN t.TYPE = 20 THEN SUM(CASE WHEN r.tID BETWEEN 6 AND 7 THEN 1 ELSE 0 END)
WHEN t.TYPE = 3 THEN SUM(CASE WHEN r.tID BETWEEN 9 AND 10 THEN 1 ELSE 0 END)
ELSE SUM(CASE WHEN r.tID > 10 THEN 1 ELSE 0 END)
END As [Times Used]
在您的情况下, r.tID
似乎达到了10,所以我假设新数据的值大于10.使用ELSE
这只会选择任何TYPE
您的CASE WHEN
子句中未考虑的值。如果涉及其他逻辑,您可能需要修改上述内容。
答案 1 :(得分:0)
您的数据结构对外人来说并不明显,对您的继任者来说也不会显而易见,使维护变得比必要的更难。通常,您可以创建两个表,一个用于Person模板,另一个用于Role模板。
那就是说,它也适用于一张桌子。当试图查找从外部表链接某个行的频率时,您应该在表上使用连接并计算结果行:
SELECT t.ID,t.Name As [Template Name],COUNT(t.ID) AS [Times used]
FROM Templates t
LEFT JOIN Person p ON(t.ID == p.tID)
LEFT JOIN Role r ON(t.ID == r.tID)
WHERE p.tID IS NOT NULL OR r.tID IS NOT NULL
GROUP BY t.ID,t.Name
这显然会高估数据库不一致导致在Person和Role表中引用模板的时间。人们当然可以解决这个问题,但是,我认为你的数据结构不值得付出更多努力...
答案 2 :(得分:0)
我的回答显示向Person和Role表添加外键,然后使用简单的CTE查询来获取总数:
MS SQL Server 2014架构设置:
CREATE TABLE Template
(
ID INTEGER PRIMARY KEY,
NAME VARCHAR(50),
Type SMALLINT
)
CREATE TABLE Person
(
ID INTEGER IDENTITY PRIMARY KEY,
TID INTEGER,
Name VARCHAR(50)
)
CREATE TABLE Role
(
ID INTEGER IDENTITY PRIMARY KEY,
TID INTEGER,
Name VARCHAR(50)
)
ALTER TABLE Person
ADD CONSTRAINT FK_Person_Template
FOREIGN KEY (TID)
REFERENCES Template(ID)
CREATE INDEX IX_Person_TID ON Person(TID)
ALTER TABLE Role
ADD CONSTRAINT FK_Role_Template
FOREIGN KEY (TID)
REFERENCES Template(ID)
CREATE INDEX IX_Role_TID ON Role(TID)
INSERT INTO Template
VALUES (1, 'Type 5', 5)
, (2, 'Type Ten', 10)
, (3, 'Type One Hundred', 100)
, (4, 'Type Twenty', 20)
, (5, 'Type Three', 3)
INSERT INTO Person (TID, Name)
VALUES (1, 'Fred')
, (1,'Mary')
, (3,'John')
, (5, 'Marty')
, (5, 'Sharon')
, (5, 'Jules')
, (5, 'Maxine')
INSERT INTO Role (TID, Name)
VALUES (2, 'Asministrator'), (2,'Developer')
, (4,'MailRoom'), (4, 'Posty'), (4, 'PA'), (4, 'HouseKeeper'), (5, 'Front Desk')
查询1 :
;WITH CTE
AS
(
SELECT Tid
FROM Person
UNION ALL
SELECT TId
FROM Role
)
SELECT T.Name As [Template Name], COUNT(*) AS [Times Used],
MAX(T.Id) As [Template Id],
MAX(T.Type) As [Template Type]
FROM Template T
INNER JOIN CTE C
ON T.Id = C.TId
GROUP BY T.Name
ORDER BY T.Name
<强> Results 强>:
| Template Name | Times Used | Template Id | Template Type |
|------------------|------------|-------------|---------------|
| Type 5 | 2 | 1 | 5 |
| Type One Hundred | 1 | 3 | 100 |
| Type Ten | 2 | 2 | 10 |
| Type Three | 5 | 5 | 3 |
| Type Twenty | 4 | 4 | 20 |
查询2 :
-- ADD A NEW TEMPLATE
INSERT INTO Template
VALUES (6, 'Type Two Hundred', 200)
-- INSERT NEW PERSON with this template
INSERT INTO Person (TID, Name)
VALUES (6, 'Malky')
<强> Results 强>: 查询3 :
-- RERUN QUERY
;WITH CTE
AS
(
SELECT Tid
FROM Person
UNION ALL
SELECT TId
FROM Role
)
SELECT T.Name As [Template Name], COUNT(*) AS [Times Used],
MAX(T.Id) As [Template Id],
MAX(T.Type) As [Template Type]
FROM Template T
INNER JOIN CTE C
ON T.Id = C.TId
GROUP BY T.Name
ORDER BY T.Name
<强> Results 强>:
| Template Name | Times Used | Template Id | Template Type |
|------------------|------------|-------------|---------------|
| Type 5 | 2 | 1 | 5 |
| Type One Hundred | 1 | 3 | 100 |
| Type Ten | 2 | 2 | 10 |
| Type Three | 5 | 5 | 3 |
| Type Twenty | 4 | 4 | 20 |
| Type Two Hundred | 1 | 6 | 200 |