あなたのテーブルは、データベースの正規化の規則に違反しています。値を 3 つの別々の列に入れることは、最適な設計ではありません。代わりに、およびテーブルの両方に対して外部キー関係を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)
それまでの間、持っている 3 つの列だけを使用する場合は、3 つの個別のサブクエリを使用するよりも優れた方法があります。
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 でライブ デモを見る
注: 私のデモでは、 forNULL
の代わりに使用しました。それが、テーブルと適切な外部キー関係を持つ唯一の方法だからです。しかし、「正しい」方法は、上で示したように、ラジオ列を新しいテーブルに移動することです。0
Radio3
Radio