0

私はテーブル機器を持っています、

テーブル装備でオールを選択した時のデータです。

select * from equipment

ここに画像の説明を入力

このテーブルの機器には、フィールド radio1、radio2、radio3 があります。

値はテーブル ラジオの ID です。これはテーブル ラジオです。

select * from radio

ここに画像の説明を入力

問題は、ラジオと機器を結合する方法です。radio1、radio2、radio3 の値は、テーブル ラジオのプロトコルです。

したがって、値は

radio1     ||     radio2    ||    radio3    ||
UDP        || Serial Number ||              ||
4

3 に答える 3

2

あなたのテーブルは、データベースの正規化の規則に違反しています。値を 3 つの別々の列に入れることは、最適な設計ではありません。代わりに、およびテーブルの両方に対して外部キー関係をEquipmentRadio持つ列を含むテーブルが必要です。次のようにできます。EquipmentID, RadioIDEquipmentRadio

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の代わりに使用しました。それが、テーブルと適切な外部キー関係を持つ唯一の方法だからです。しかし、「正しい」方法は、上で示したように、ラジオ列を新しいテーブルに移動することです。0Radio3Radio

于 2013-07-25T06:14:09.267 に答える
0

テーブルを区別するためにエイリアスを使用して、 のフィールドradioごとに 1 回結合する必要があります。radio...equipmentradio

SELECT equipment.*, Radio1.protocol, Radio2.protocol, Radio3.protocol 
FROM equipment INNER JOIN radio as Radio1 ON Radio1.id=equipment.radio1 INNER JOIN radio as Radio2 ON Radio2.id=equipment.radio2 INNER JOIN radio as Radio3 ON Radio3.id=equipment.radio3
于 2013-07-25T04:26:03.960 に答える
0

テーブルの設計が不十分な場合は、テーブルを正規化する必要があります。しかし、あなたが言ったように必要な場合。以下は unefficeint メソッドになりますが、動作するかどうかを確認してください。

select (select protocal from radio where id=equipemnt.radio1 ) as radio1,
(select protocal from radio where id=equipemnt.radio2 ) as radio2,
(select protocal from radio where id=equipemnt.radio3 ) as radio3
from equipment
于 2013-07-25T04:26:14.447 に答える