查询显示外键

时间:2013-07-25 04:16:46

标签: sql sql-server sql-server-2008

我有桌子设备,

当我选择所有桌面设备时,这是一个数据。

select * from equipment

enter image description here

在此表设备中有现场radio1,radio2,radio3

值是来自表格收音机的ID,这里是tabel收音机

select * from radio

enter image description here

问题是如何加入无线电和设备,我需要 radio1,radio2,radio3值是来自表格无线电的协议

所以值是

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

3 个答案:

答案 0 :(得分:2)

您的表违反了数据库规范化规则。将值分成三个单独的列并不是最好的设计。相反,您应该有一个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)

与此同时,如果你 只使用你拥有的三列,那么比使用三个独立的子查询更好。

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列。为了适应非规范化的设计,这很笨拙。

See a Live Demo at SQL Fiddle

注意:在我的演示中,我使用NULL代替0 Radio3,因为这是与Radio表建立正确外键关系的唯一方法。但是,正确的方法是将无线电列移动到新表中,如上所示。

答案 1 :(得分:0)

您需要为radio中的每个radio...字段加入equipment一次,使用别名来区分radio表:

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

答案 2 :(得分: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