SQL - 搜索将来可能创建的值

时间:2015-06-08 09:06:00

标签: sql sql-server sql-server-2012

我有一个包含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值。

3 个答案:

答案 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查询来获取总数:

SQL Fiddle

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 |