【问题标题】:INNER JOIN multiple columns to same column from another tableINNER JOIN 多个列到另一个表的同一列
【发布时间】:2021-04-28 14:49:39
【问题描述】:

我得到了hmmd_prm 表:

| id |  hmmd_id  |  prm1  |  prm2  |  prm3  |  prm4  |  prm5  |  prm6  |  prm7  |  prm8  |  prm9  |  prm10 |
| 1  |     2     |   1    |   2    |   3    |   1    |   2    |   3    |   1    |   2    |  null  |  null  |
| 2  |     3     |   4    |   3    |   2    |   1    |   4    |   3    |   2    |   1    |   4    |   3    |

lab_prm 表是:

| prm_id |  prm_adi  |  prm_adgr  |  prm_udgr  |  prm_birim  |  prm_ctrl  |
|   1    |    pH     |
|   2    |    O2     |
|   3    | peroxide  |
|   4    |    hum    |

和 main_hmmd 表,该表具有名称并使用 hmmd_id 提取名称

我试图得到这样的结果:

| id |  hmmd_id  |  prm1  |  prm2  |  prm3  |  prm4  |  prm5  |  prm6  |  prm7  |  prm8  |  prm9  |  prm10 |
| 1  |   BUGDAY  |   pH   |   O2   | prxide |   pH   |   O2   | prxide |   pH   |   O2   |  null  |  null  |

我正在使用这样的东西:

SELECT hp.id, mh.hmmd_adi, lp1.prm_adi, lp2.prm_adi, lp3.prm_adi, lp4.prm_adi, lp5.prm_adi, lp6.prm_adi, lp7.prm_adi, lp8.prm_adi, lp9.prm_adi, lp10.prm_adi
FROM std_tbl_hmmd_prm AS hp
INNER JOIN std_tbl_main_hmmd AS mh ON mh.id = hp.hmmd_id
INNER JOIN std_tbl_lab_prm AS lp1 ON hp.prm1 = lp1.prm_id
INNER JOIN std_tbl_lab_prm AS lp2 ON hp.prm2 = lp2.prm_id
INNER JOIN std_tbl_lab_prm AS lp3 ON hp.prm3 = lp3.prm_id
INNER JOIN std_tbl_lab_prm AS lp4 ON hp.prm4 = lp4.prm_id
INNER JOIN std_tbl_lab_prm AS lp5 ON hp.prm5 = lp5.prm_id
INNER JOIN std_tbl_lab_prm AS lp6 ON hp.prm6 = lp6.prm_id
INNER JOIN std_tbl_lab_prm AS lp7 ON hp.prm7 = lp7.prm_id
INNER JOIN std_tbl_lab_prm AS lp8 ON hp.prm8 = lp8.prm_id
INNER JOIN std_tbl_lab_prm AS lp9 ON hp.prm9 = lp9.prm_id
INNER JOIN std_tbl_lab_prm AS lp10 ON hp.prm10 = lp10.prm_id

它按我的意愿工作,但我很确定有更好的解决方案。

我怎样才能让这更简单?

提前致谢。

更新: 我想要实现的是,在 hmmd_prm 表中,我有一些材料为hmmd_id,用户将对这些参数应用一些参数。我为参数设置了 10 列,因此用户最多可以分配 10 个参数,但也可以分配 1 或 2 个参数,其余为空。

这可能不是最好的解决方案,因为这是我第一次做这样的事情,但我只是不希望结果显示为每行中具有不同参数的相同材料的多个条目,如下所示。

| id |  hmmd_id  |  prms  |
| 1  |     2     |   1    |
| 2  |     2     |   2    |
| 3  |     2     |   3    |
| 4  |     2     |   1    |
| 5  |     2     |   2    |
| 6  |     2     |   3    |
| 7  |     2     |   1    |

【问题讨论】:

  • 我认为您希望在那里进行左连接——正如所写的那样,查询不会给出这些结果(除了示例中没有所有数据。)
  • 你是对的!我想我错过了解决这个烂摊子的更好方法
  • 我不认为这是一团糟——在这种情况下左连接在关系数据模型中是可以接受的,并且如果您的数据库配置正确,则性能良好。我个人总是这样做,不做似乎总是表现更差的支点。

标签: sql sql-server inner-join


【解决方案1】:

SQL 和关系数据库是同一枚硬币的两面,它们都在其设计中融入了规范化的数据结构。

这只是一个迹象,表明您处理的结构不适合 SQL,因此也不适合关系数据库。 (代码味道。)

因此,一些重复可以通过动态规范化结构来移除,然后如果您必须再次去规范化。

SELECT
  hp.id,
  mh.hmmd_adi,
  MAX(CASE WHEN pivot_prm.col_id =  1 THEN lp.prm_adi END)   AS prm1,
  MAX(CASE WHEN pivot_prm.col_id =  2 THEN lp.prm_adi END)   AS prm2,
  MAX(CASE WHEN pivot_prm.col_id =  3 THEN lp.prm_adi END)   AS prm3,
  MAX(CASE WHEN pivot_prm.col_id =  4 THEN lp.prm_adi END)   AS prm4,
  MAX(CASE WHEN pivot_prm.col_id =  5 THEN lp.prm_adi END)   AS prm5,
  MAX(CASE WHEN pivot_prm.col_id =  6 THEN lp.prm_adi END)   AS prm6,
  MAX(CASE WHEN pivot_prm.col_id =  7 THEN lp.prm_adi END)   AS prm7,
  MAX(CASE WHEN pivot_prm.col_id =  8 THEN lp.prm_adi END)   AS prm8,
  MAX(CASE WHEN pivot_prm.col_id =  9 THEN lp.prm_adi END)   AS prm9,
  MAX(CASE WHEN pivot_prm.col_id = 10 THEN lp.prm_adi END)   AS prm10
FROM
  std_tbl_hmmd_prm   AS hp
INNER JOIN
  std_tbl_main_hmmd  AS mh
    ON mh.id = hp.hmmd_id
CROSS APPLY
(
  VALUES
    ( 1, hp.prm1 ),
    ( 2, hp.prm2 ),
    ( 3, hp.prm3 ),
    ( 4, hp.prm4 ),
    ( 5, hp.prm5 ),
    ( 6, hp.prm6 ),
    ( 7, hp.prm7 ),
    ( 8, hp.prm8 ),
    ( 9, hp.prm9 ),
    (10, hp.prm10)
)
  AS pivot_prm(col_id, prm_id)
INNER JOIN
  std_tbl_lab_prm   AS lp
    ON pivot_prm.prm_id = lp.prm_id
GROUP BY
  hp.id,
  mh.hmmd_adi

我个人建议不要使用GROUP BYMAX(CASE) 对结果进行反规范化,而只需使用...

SELECT
  hp.id,
  mh.hmmd_adi,
  pivot_prm.col_id,
  lp.prm_adi
FROM
  std_tbl_hmmd_prm   AS hp
INNER JOIN
  std_tbl_main_hmmd  AS mh
    ON mh.id = hp.hmmd_id
CROSS APPLY
(
  VALUES
    ( 1, hp.prm1 ),
    ( 2, hp.prm2 ),
    ( 3, hp.prm3 ),
    ( 4, hp.prm4 ),
    ( 5, hp.prm5 ),
    ( 6, hp.prm6 ),
    ( 7, hp.prm7 ),
    ( 8, hp.prm8 ),
    ( 9, hp.prm9 ),
    (10, hp.prm10)
)
  AS pivot_prm(col_id, prm_id)
INNER JOIN
  std_tbl_lab_prm   AS lp
    ON pivot_prm.prm_id = lp.prm_id

这将使许多后续查询变得更加简单。

【讨论】:

    【解决方案2】:

    您可以规范化 hmmd_prm 使其成为一个相交表(多对多)。您没有提供有关数据的足够信息,无法知道这是否可行。如果 prm1、prm2 等具有任何意义,您可能还需要一个值为 1 到 10 的位置列。

    | Id | hmmd_id | prm_id | prm_position |
    | 1  | 2       | 1      | 1            |
    | 1  | 2       | 1      | 2            |
    | 1  | 2       | 1      | 3            |
    | 1  | 2       | 1      | 4            |
    

    等等

    然后您可以在 hmmd_id、prm_id 和 prm_position 之间创建唯一约束以确保完整性。

    【讨论】:

    • 这给我的印象更像是评论而不是答案。
    • 这就是电话接听时的问题......很难创建一个好的例子。
    • 是的,我通常也通过电话接听。这……辛苦了
    • @Andrew - 所以你承认在这个答案中打电话?好电话。
    • 我实际上并不确定我使用的结构是否对此有好处,因为我以前从未做过这样的事情。我更新了关于我想要实现的目标的问题。为了“回答的问题”,我将选择@MatBailie 的答案,因为它是对实际问题“我怎样才能让这个更简单?”的回答。我问这个问题只是因为查询感觉很糟糕,因为它是重复的,我觉得做错了什么。不过,我会尽力为我的情况找到更好的解决方案,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2017-06-25
    • 1970-01-01
    相关资源
    最近更新 更多