您的表违反了数据库规范化规则。将值放在三个单独的列中并不是最好的设计。相反,您应该有一个EquipmentRadio
表,其中的列与和表EquipmentID, RadioID
都有外键关系。你可以这样做:Equipment
Radio
CREATE TABLE dbo.EquipmentRadio (
EquipmentID int NOT NULL CONSTRAINT FK_EquipmentRadio_EquipmentID
FOREIGN KEY REFERENCES dbo.Equipment(ID),
RadioID int NOT NULL CONSTRAINT FK_EquipmentRadio_RadioID
FOREIGN KEY REFERENCES dbo.Radio(ID),
CONSTRAINT PK_EquipmentRadio PRIMARY KEY CLUSTERED (EquipmentID, RadioID)
);
INSERT dbo.EquipmentRadio
SELECT
E.ID
FROM
dbo.Equipment E
CROSS APPLY (VALUES
(E.Radio1),
(E.Radio2),
(E.Radio3)
) R (RadioID)
WHERE
R.RadioID IS NOT NULL -- or `> 0` if appropriate
;
ALTER TABLE dbo.EquipmentRadio DROP COLUMN Radio1;
ALTER TABLE dbo.EquipmentRadio DROP COLUMN Radio2;
ALTER TABLE dbo.EquipmentRadio DROP COLUMN Radio3;
当然,不要这样做,尤其是删除列部分,除非你确定它是正确的。要使用此设计,您必须适当地修改前端客户端表单和代码。
您的表格将如下所示:
EquipmentID RadioID
----------- -------
1 1
1 2
-- (notice there's no third row, but you could have 3 or even more)
同时,如果您打算只使用您拥有的三列,则比使用三个单独的子查询更好。
SELECT
E.ID,
R.* -- should name the columns explicitly, though
FROM
dbo.Equipment E
OUTER APPLY (
SELECT
P.*
FROM
(
SELECT U.Radio, R.Protocol
FROM
(VALUES
('Radio1', E.Radio1),
('Radio2', E.Radio2),
('Radio3', E.Radio3)
) U (Radio, RadioID)
INNER JOIN dbo.Radio R
ON U.RadioID = R.ID
WHERE
U.RadioID IS NOT NULL -- or `> 0` if appropriate
) X
PIVOT (Max(X.Protocol) FOR X.Radio IN (Radio1, Radio2, Radio3)) P
) R
;
这样做是暂时将 3 个值取消旋转为 3 行(就像规范化数据库一样),然后将它们加入到 的单个连接中Radio
,然后最终将它们旋转回 3 列。要适应非规范化的设计,要经历很多笨拙的事情。
在 SQL Fiddle 上查看现场演示
注意:在我的演示中,我使用NULL
而不是0
for,Radio3
因为这是与表建立正确外键关系的唯一方法Radio
。但是“正确”的方法是将单选列移动到一个新表中,正如我在上面向您展示的那样。