SQL 多个关节(将是 10 个连接)在同一 table 上的有效解决方案(查找 table)
SQL efficient solution for mutilple joins (could be 10 joins) on same table (lookup table)
我们已经实现了一个查找 table,其中包含一个 ID 和一个文本字段。然后,我的 table 仅包含不同字段值的 LookupID。例如...
Table
- TableID、StatusID、TypeID、DocID
值看起来像这样
- 1、2、3、4
查找Table
- LookupID,文本
值看起来像这样
- 1,一些值
- 2、我的状态文本
- 3、我的类型文字
- 4、我的文档文字
我需要知道的是,这是否是查询这些 table 的最有效解决方案(创建 sql 数据视图,其中显示的是文本而不是 ID)
SELECT T.TableID, L1.Text as StatusText, L2.Text as TypeText, L3.Text as DocText
FROM Table T
LEFT JOIN LookupTable L1 on L1.LookupID = T.StatusID
LEFT JOIN LookupTable L2 on L2.LookupID = T.TypeID
LEFT JOIN LookupTable L3 on L3.LookupID = T.DocID
... 还是子查询更适合此解决方案?像这样。
SELECT T.TableID,
(SELECT L.Text FROM LookupTable L WHERE L.LookupID = T.StatusID) as StatusText,
(SELECT L.Text FROM LookupTable L WHERE L.LookupID = T.TypeID) as TypeText,
(SELECT L.Text FROM LookupTable L WHERE L.LookupID = T.DocID) as DocText
FROM Table T
...或者有更好的解决办法吗?请记住,对于此示例,我只加入了 3 次,并且需要加入 10 次或更多次。
您是否考虑过使用 UNPIVOT 来破解它?
您最好的选择是为数据库中的每个单独的实体创建单独的查找 table。如果您需要为单个查找类型添加附加属性(例如,现在您需要跟踪每个州的州鸟,但这肯定与汽车模型无关),这将为您提供更好的灵活性。根据我的经验 "generic" 数据库设计模式通常会变得很糟糕。有目的的设计。
一旦你有了它,只要你有适当的索引,有多个 JOIN
s 几乎总是(如果不是总是)比子查询执行得更好:
SELECT
P.person_id,
S.state_name,
G.movie_genre_name,
...
FROM
Person P
INNER JOIN [State] S ON S.state_id = P.home_state_id
INNER JOIN Movie_Genre G ON G.movie_genre_id = P.favorite_movie_genre_id
...
此外,请记住,您系统中的每个列表不一定都是查找 table。例如,性别之类的东西可以简单地通过 CHECK CONSTRAINT
:
来维护
gender VARCHAR(15) NULL CONSTRAINT CHK_Person_Gender CHECK (gender IN ('Male', 'Female', 'Transgender'))
或:
severity VARCHAR(10) NOT NULL CONSTRAINT CHK_Ticket_Severity CHECK (severity IN ('High', 'Medium', 'Low'))
这与基本上只是一个名称的列表相关。包含具有附加属性的项目的列表或可能随时间频繁更改的列表应放入 table.
我们已经实现了一个查找 table,其中包含一个 ID 和一个文本字段。然后,我的 table 仅包含不同字段值的 LookupID。例如...
Table
- TableID、StatusID、TypeID、DocID
值看起来像这样
- 1、2、3、4
查找Table
- LookupID,文本
值看起来像这样
- 1,一些值
- 2、我的状态文本
- 3、我的类型文字
- 4、我的文档文字
我需要知道的是,这是否是查询这些 table 的最有效解决方案(创建 sql 数据视图,其中显示的是文本而不是 ID)
SELECT T.TableID, L1.Text as StatusText, L2.Text as TypeText, L3.Text as DocText
FROM Table T
LEFT JOIN LookupTable L1 on L1.LookupID = T.StatusID
LEFT JOIN LookupTable L2 on L2.LookupID = T.TypeID
LEFT JOIN LookupTable L3 on L3.LookupID = T.DocID
... 还是子查询更适合此解决方案?像这样。
SELECT T.TableID,
(SELECT L.Text FROM LookupTable L WHERE L.LookupID = T.StatusID) as StatusText,
(SELECT L.Text FROM LookupTable L WHERE L.LookupID = T.TypeID) as TypeText,
(SELECT L.Text FROM LookupTable L WHERE L.LookupID = T.DocID) as DocText
FROM Table T
...或者有更好的解决办法吗?请记住,对于此示例,我只加入了 3 次,并且需要加入 10 次或更多次。
您是否考虑过使用 UNPIVOT 来破解它?
您最好的选择是为数据库中的每个单独的实体创建单独的查找 table。如果您需要为单个查找类型添加附加属性(例如,现在您需要跟踪每个州的州鸟,但这肯定与汽车模型无关),这将为您提供更好的灵活性。根据我的经验 "generic" 数据库设计模式通常会变得很糟糕。有目的的设计。
一旦你有了它,只要你有适当的索引,有多个 JOIN
s 几乎总是(如果不是总是)比子查询执行得更好:
SELECT
P.person_id,
S.state_name,
G.movie_genre_name,
...
FROM
Person P
INNER JOIN [State] S ON S.state_id = P.home_state_id
INNER JOIN Movie_Genre G ON G.movie_genre_id = P.favorite_movie_genre_id
...
此外,请记住,您系统中的每个列表不一定都是查找 table。例如,性别之类的东西可以简单地通过 CHECK CONSTRAINT
:
gender VARCHAR(15) NULL CONSTRAINT CHK_Person_Gender CHECK (gender IN ('Male', 'Female', 'Transgender'))
或:
severity VARCHAR(10) NOT NULL CONSTRAINT CHK_Ticket_Severity CHECK (severity IN ('High', 'Medium', 'Low'))
这与基本上只是一个名称的列表相关。包含具有附加属性的项目的列表或可能随时间频繁更改的列表应放入 table.