【问题标题】:Join two tables with null value连接两个空值的表
【发布时间】:2012-08-14 20:33:03
【问题描述】:

我有一个表Visit,其中有VisitIDPatientIDDoctorID 等列,还有PrescriptionID 列。在表Prescription 中有列PrescriptionIDDrugID(它们是我的主键)。一个处方可以有很多药,所以会有这样的:

处方 ID:1 药物 ID:38
处方 ID:1 药物 ID:278
处方 ID:1 药物 ID:7

Visit 表中,将插入“1”值作为PrescriptionID。但是现在我不能用外键加入这两个表,因为不是每次访问都有处方,所以PrescriptionID 可以为空,我有错误,列必须是主键或必须是唯一的。如何以其他方式加入这些表?

【问题讨论】:

  • 请显示导致此错误的查询。
  • ALTER TABLE Prescription ADD FOREIGN KEY (PrescriptionID) REFERENCES Visit(PrescriptionID)
  • 您实际上需要PrescriptionID 做什么?根据您所说,VisitIDPrescriptionID 之间存在 1:1* 的关系。 Prescription 表不能使用VisitID 作为外列吗?
  • PrescriptionID 必须采用特定格式(20 个字符,每个字符都表示某种含义等),因此它与 VisitID 无关。
  • 我并不是要完全摆脱PrescriptionID - 只是让Prescriptions 表使用FK 来代替VisitID

标签: sql sql-server join


【解决方案1】:

您似乎在这里谈论两个不同的问题。

一个问题是,您希望在引用列中允许空值。这很简单,您只需要将列定义为可为空的 作为外键。该键应该引用的是另一个问题,这将我们引向我在您的问题中可以看到的两个问题中的另一个。

关于必须是主键或唯一列的错误与引用表使用 单个 列来引用复合(由两列组成)键这一事实有关。而且您不能仅引用键的一部分,因为引用必须是特定的 single 行,而您的 Visit.PrescriptionID 值可能会引用多个(这是正确的,因为行参考表中的不是真正的处方,而是处方项目)。这就是为什么告诉您该列必须是主键或唯一的原因。

因此,我建议按如下方式更改您的架构:

  1. 让您的Prescription 表仅包含作为实体的处方。即使除了键没有其他属性,也让它存储在自己的表中:

    CREATE TABLE Presciption (
      PrescriptionID int
        IDENTITY  /* just an assumption */
        CONSTRAINT PK_Prescription PRIMARY KEY
    );
    
  2. 您当前的Prescription 表应重命名为PrescriptionItemPrescriptionDrug,遵循您的单数名词命名约定。它的PrescriptionID 列将是引用Prescription.PrescriptionID 的外键,如下所示:

    CREATE TABLE PresciptionDrug (
      PrescriptionID int NOT NULL
        CONSTRAINT FK_PrescriptionDrug_Prescription
        FOREIGN KEY REFERENCING Prescription (PrescriptionID),
      DrugID int NOT NULL
        CONSTRAINT FK_PrescriptionDrug_Drug
        FOREIGN KEY REFERENCING Drug (DrugID),
      CONSTRAINT PK_PrescriptionDrug
        PRIMARY KEY (PrescriptionID, DrugID)
    );
    
  3. 现在您可以像这样在Visit.PrescriptionID 上定义外来语:

    ALTER TABLE Visit
    ADD CONSTRAINT FK_Visit_Prescription
        FOREIGN KEY REFERENCING Prescription (PrescriptionID)
    ;
    

    如果您想为就诊提供可选处方,请不要忘记确保该列可以为空。 (可以为空的外键在 SQL Server 中非常好。)

【讨论】:

    【解决方案2】:

    我觉得表结构应该是

    Visit (VisitID, Time, .....) --no prescriptionID
    Prescription (PrescriptionID, ..... , VisitID) --VisitID as FK
    PrescriptionDrugs(PrescriptionID, DrugID) -- Both columns as PK
    

    那么您的查询将是

    SELECT v.VisitID FROM Visit v
    LEFT JOIN Prescription p ON v.VisitID = p.VisitID
    LEFT JOIN PrescriptionDrugs pd ON p.PrescriptionID = pd.PrescriptionID
    

    这会给你类似的东西

    VisitID        PrescriptionID      DrugID
    101            ABC                 Anti-Bio
    101            ABC                 Asprin
    102            BAC                 Anti-Bio
    

    意思是 Visit 101 有 2 种药物,Visit 102 有 1 种药物

    无论如何,使用您当前的架构,试试这个

    select v.visitid, v.presid, p.drugid 
    from visit v 
    left join prescription p on v.presid = p.presid
    

    【讨论】:

      【解决方案3】:

      你问怎么做:

      select *
        from Visit as V left outer join
          Prescription as P on P.PrescriptionId = V.PrescriptionId
      

      这将返回所有访问和任何适用的处方。没有处方的访问将导致没有处方数据的输出行。

      【讨论】:

        猜你喜欢
        • 2015-06-19
        • 2015-07-13
        • 2021-05-08
        • 2021-02-04
        • 2021-05-20
        • 1970-01-01
        • 2017-08-30
        • 2023-04-09
        • 1970-01-01
        相关资源
        最近更新 更多