0

I have a table with category codes which listed in another table, there are 8 category codes and currently I'm doing the below (below is massively simplified):

SELECT HeaderCode
     , C1.CategoryName AS C1
     , C2.CategoryName AS C2
     , C3.CategoryName AS C3
     , C4.CategoryName AS C4
     , C5.CategoryName AS C5
     , C6.CategoryName AS C6
     , C7.CategoryName AS C7
     , C8.CategoryName AS C8


FROM Header H
INNER JOIN Cats C1 ON H.Cat1 = C1.CategoryID
INNER JOIN Cats C2 ON H.Cat2 = C2.CategoryID
INNER JOIN Cats C3 ON H.Cat3 = C3.CategoryID
INNER JOIN Cats C4 ON H.Cat4 = C4.CategoryID
INNER JOIN Cats C5 ON H.Cat5 = C5.CategoryID
INNER JOIN Cats C6 ON H.Cat6 = C6.CategoryID
INNER JOIN Cats C7 ON H.Cat7 = C7.CategoryID
INNER JOIN Cats C8 ON H.Cat8 = C8.CategoryID

SQL Fiddle Example

I did think about a function to get the data but it would be slow as there are 200,000+ records I need to get this information for.

Performance is so far fine but there are times I have to use dynamic SQL and doing this with another 5+ joins is a big mess.

Is there a better/more convenient/easier to maintain way to do this?

4

2 回答 2

1

假设您无法修复您的架构(意思是规范化您的架构),您可以像这样创建一个 Inline(!) 表值函数:

CREATE FUNCTION dbo.EightCats(@C1 INT, @C2 INT, @C3 INT, ...)
RETURNS TABLE
AS
RETURN
 SELECT * 
   FROM (SELECT CategoryName AS C1 FROM dbo.Cats WHERE CategoryId = @C1) T1
   CROSS JOIN (SELECT CategoryName AS C2 FROM dbo.Cats WHERE CategoryId = @C2) T2
   CROSS JOIN (SELECT CategoryName AS C3 FROM dbo.Cats WHERE CategoryId = @C2) T3
   ...

然后你可以这样写你的查询:

SELECT H.HeaderCode, EC.*
  FROM dbo.Header H
 CROSS APPLY dbo.EightCats(H.Cat1,H.Cat2,H.Cat3,H.Cat4,H.Cat5,H.Cat6,H.Cat7,H.Cat8) EC;

这应该导致相同的执行计划,因此不应该有性能损失。重要的是您仅将其用于八个类别。如果您有另一个只有七个类别的查询,则需要创建一个新函数。否则,您(或者更确切地说是 SQL Server)最终会进行不必要的连接。

于 2013-04-24T14:31:40.333 回答
0

我会用桥牌桌来做到这一点。

CREATE TABLE HeaderCategory (
  HeaderCategoryId int IDENTITY(1,1) NOT NULL
, HeaderId int
, CategoryId int
, SortBy int
)

并将 HeaderId 和 CategoryId 外键设置为各自的表。SortBy 列用于表示是 Category1、2、3 等。

这是更“规范化”的架构。

然后,要获得与您的问题相同的查询输出,请执行简单的 PIVOT 查询。

如果您不想更改表,还有两种可能性:1)编写一个 GetCategoryName(CategoryId) 函数,并在您的选择中使用它,如下所示:SELECT Header, GetCategoryName(Category1) AS C1, ...

2) 创建一个包含 CategoryNames 的 VIEW。

于 2013-04-24T14:31:53.920 回答