【问题标题】:Joining multiple columns in one table to a single column in another table将一个表中的多个列连接到另一个表中的单个列
【发布时间】:2010-10-20 16:12:48
【问题描述】:

我希望创建一个从两个表“Schedule”和“Reference”中提取数据的视图。

Schedule 有 50 多列(它几乎完全是非规范化的——不是我的设计),其中大部分包含一个可以连接到 Reference 表中的列的值。

如何编写 SQL 语句以将 Schedules 中的每一列正确连接到 Reference 中的单个列?

Schedule 表定义为:

    CREATE TABLE [dbo].[Schedule](
    [ID] [int] NOT NULL,
    [SCHEDULEWEEK] [datetime] NOT NULL,
    [EMPNO] [numeric](10, 0) NOT NULL,
    [EMPLNAME] [varchar](32) NULL,
    [EMPFNAME] [varchar](32) NULL,
    [EMPSENDATE] [datetime] NULL,
    [EMPHIREDATE] [datetime] NULL,
    [EMPTYPE] [char](1) NULL,
    [EMPSTATUS] [char](1) NULL,
    [SNREFUSALS] [tinyint] NULL,
    [QUALSTRING] [varchar](128) NULL,
    [JOBOVERSHIFTTYPE] [bit] NULL,
    [SHORTNOTICE] [bit] NULL,
    [SHORTNOTICEWAP] [bit] NULL,
    [SHORTNOTICEPHONE] [varchar](32) NULL,
    [LEADHAND] [bit] NULL,
    [DUALCURRENCY] [bit] NULL,
    [MIN100WINDOW] [bit] NULL,
    [STATHOLIDAY] [bit] NULL,
    [AREAOVERHOURS] [bit] NULL,
    [DOUBLEINTERZONES] [bit] NULL,
    [MAXDAYSPERWEEK] [tinyint] NULL,
    [MAXHOURSPERWEEK] [numeric](10, 2) NULL,
    [MAXHOURSPERSHIFT] [numeric](10, 2) NULL,
    [MAXDOUBLESPERWEEK] [tinyint] NULL,
    [ASSIGNEDDAYS] [tinyint] NULL,
    [ASSIGNEDHOURS] [numeric](10, 2) NULL,
    [ASSIGNEDDOUBLES] [tinyint] NULL,
    [ASSIGNEDLOAHOURS] [numeric](10, 2) NULL,
    [SHIFTNO1] [int] NULL,
    [TEXT1_1] [varchar](64) NULL,
    [TEXT2_1] [varchar](64) NULL,
    [DAYFLAG1] [bit] NULL,
    [COMMENT1] [text] NULL,
    [SHIFTNO2] [int] NULL,
    [TEXT1_2] [varchar](64) NULL,
    [TEXT2_2] [varchar](64) NULL,
    [DAYFLAG2] [bit] NULL,
    [COMMENT2] [text] NULL,
    [SHIFTNO3] [int] NULL,
    [TEXT1_3] [varchar](64) NULL,
    [TEXT2_3] [varchar](64) NULL,
    [DAYFLAG3] [bit] NULL,
    [COMMENT3] [text] NULL,
    [SHIFTNO4] [int] NULL,
    [TEXT1_4] [varchar](64) NULL,
    [TEXT2_4] [varchar](64) NULL,
    [DAYFLAG4] [bit] NULL,
    [COMMENT4] [text] NULL,
    [SHIFTNO5] [int] NULL,
    [TEXT1_5] [varchar](64) NULL,
    [TEXT2_5] [varchar](64) NULL,
    [DAYFLAG5] [bit] NULL,
    [COMMENT5] [text] NULL,
    [SHIFTNO6] [int] NULL,
    [TEXT1_6] [varchar](64) NULL,
    [TEXT2_6] [varchar](64) NULL,
    [DAYFLAG6] [bit] NULL,
    [COMMENT6] [text] NULL
-- Snip
) ON [PRIMARY]

而Reference表定义为:

CREATE TABLE [dbo].[Reference](
    [ID] [int] NOT NULL,
    [CODE] [varchar](21) NOT NULL,
    [LOCATIONCODE] [varchar](4) NOT NULL,
    [SCHAREACODE] [varchar](16) NOT NULL,
    [LOCATIONNAME] [varchar](32) NOT NULL,
    [FLTAREACODE] [varchar](16) NOT NULL
) ON [PRIMARY]

我正在尝试将 Schedule 中的每个 [TEXT1_]/[TEXT2_] 列加入到参考中的 [SCHAREACODE] 列。参考表包含的所有内容都是员工可以工作的区域列表。

【问题讨论】:

  • 请用您的表格示例和您正在使用的 RDBMS 更新您的问题 - 例如MySQL、SQL Server 等
  • Schedules 中的每一列是否都连接到引用中的 COLUMN - 或者您实际上是指 ROW?请提供一个示例(例如 50 列中的 3 列。)
  • TEXTn 是逗号分隔列表还是只是一个区号?
  • 这真的很有趣。你的意思是,TEXT*_* 是SHAREACODE 的外键? SHAREACODE 在参考表中是唯一的吗?或者它可以指向许多参考资料吗?我问是因为它不使用主键...
  • 是的,TEXT*_* 是 SHAREACODE 的外键。本质上,Schedule 中的每一行都是指员工一周的日程安排。一排,一星期。 28 个可能的班次,所以 28 列。嗯,56 列,因为有一个与班次相关的注释......

标签: sql


【解决方案1】:

尝试这样的查询:

select s.*, r.schareacode from schedule s, 
where 
s.text1_1 = s.schareacode
or s.text2_1 = s.schareacode
or s.textx_x = s.schareacode
..

您应该能够使用传统联接获得相同的结果,因此我建议您也尝试一下。

【讨论】:

    【解决方案2】:

    同意 TheSoftwareJedi,但我可以建议使用 LEFT JOIN,以便匹配失败不会导致您的计划行消失吗?

    当然,无论细节如何,做 28 次 JOIN 都会有点麻烦。

    我不确定我是否会称其为“非规范化”,更多的是“异常化”...... :-)

    【讨论】:

    • 我想这取决于:如果您的数据库意识到您正在加入同一个表,那么它可能会意识到将该表放入内存中的哈希是一个合理的计划。架构不漂亮,但我见过更糟糕的情况。
    【解决方案3】:

    来自更新的问题

    也许是这样的?不管你做什么都会很乱。

    SELECT S.ID
      S.TEXT1_1,
      TEXT1_1_RID = COALESCE((SELECT MAX(R.ID) FROM Reference R WHERE R.SCHAREACODE = S.TEXT1_1), 0),
      S.TEXT1_2,
      TEXT1_2_RID = COALESCE((SELECT MAX(R.ID) FROM Reference R WHERE R.SCHAREACODE = S.TEXT1_2), 0),
      ...
    FROM Schedule S
    

    【讨论】:

    • 我怀疑这可能是唯一的方法。
    【解决方案4】:

    你的描述有点欠缺,所以我会假设

    Schedule 有 50 多列(它几乎完全是非规范化的——不是我的设计),其中大部分包含一个可以连接到 Reference 表中的列的值。

    表示 Schedule 中 50 多列中有 1 列是 ReferenceId。所以,给定这样的表格设计:

    Schedule ( MaybeReferenceId1, MaybeReferenceId2, MaybeReferenceId3, ... )
    Reference ( ReferenceId )
    

    类似:

    SELECT *
    FROM Schedule
    JOIN Reference ON
         Schedule.MaybeReferenceId1 = Reference.ReferenceId
         OR Schedule.MaybeReferenceId2 = Reference.ReferenceId
         OR Schedule.MaybeReferenceId3 = Reference.ReferenceId
         OR Schedule.MaybeReferenceId4 = Reference.ReferenceId
         ...
    

    会起作用的。如果您的 RDBMS 支持,您可以使用 IN 来简化它:

    SELECT *
    FROM Schedule
    JOIN Reference ON
         Reference.ReferenceId IN (
            Schedule.MaybeReferenceId1,
            Schedule.MaybeReferenceId2,
            Schedule.MaybeReferenceId3,
            Schedule.MaybeReferenceId4,
            ...
         )
    

    【讨论】:

      【解决方案5】:

      我认为他的意思是多次加入参考表:

      SELECT *
        FROM Schedule AS S
       INNER JOIN Reference AS R1 
               ON R1.ID = S.FirstID 
       INNER JOIN Reference AS R2 
               ON R2.ID = S.SecondID 
       INNER JOIN Reference AS R3 
               ON R3.ID = S.ThirdID 
       INNER JOIN Reference AS R4 
               ON R4.ID = S.ForthID 
      

      【讨论】:

      • 如果我想从参考表中选择几列怎么办?会不会像“选择 R1.ID、R2.ID、R3.ID、R4.ID ......”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      • 2020-06-23
      • 2023-03-06
      相关资源
      最近更新 更多