根据任意列中不同列中的值集联接表

时间:2019-07-15 10:21:36

标签: sql database tsql

我在工作中遇到一个问题,我对SQL或一般的数据库知之甚少,以至于甚至不知道如何搜索。

因此,在对StackOverflow问题进行了无数次“观看”之后,这是我的第一个问题。

我有两个表,彼此之间没有其他关系,除了同一组列(我将它们称为item_1至item_3)之外,它们中的值以随机顺序排列。 我需要连接这些表,但是我不能只将它们连接到每一列,因为我正在寻找相同的项目任何顺序。 两个表中的集合必须相同(没有更多,没有更少),但位置无关紧要。

这里有一些虚拟表(希望)解释我的意思:

表1

user_id | use_name | item_1 | item_2 | item_3
--------+----------+--------+--------+--------
 1      | Tim      | A      | B      | NULL
 2      | Tom      | NULL   | NULL   | C
 3      | Sam      | A      | NULL   | NULL

table2

role     | item_1 | item_2 | item_3
---------+--------+--------+--------
type1    | A      | NULL   | B
type2    | A      | B      | C
type3    | A      | NULL   | NULL

我正在寻找一个选择/联接,它会产生一个这样的表:

user_name | role
----------+------
Tim       | type1
Sam       | type3

我尝试了一个排列表,但在实际情况中,我们不是在考虑3列而是10列,这似乎不是最好的解决方案。 我目前正在尝试通过枢轴/枢轴实现一些有用的操作,但到目前为止没有任何结果。

我什至只对文章链接感到非常满意。甚至是我遇到的问题的独特名称,我都可以用Google搜索:)

非常感谢您!

1 个答案:

答案 0 :(得分:1)

如果我的理解正确,那么您希望各行之间完全匹配,其中各项需要完全匹配。

您的数据模型较差。在数据库中,不应将重复的值存储在列中。相反,您应该将它们存储在行中。

但是,取消数据透视很简单:

with t1 as (
      select t1.*, v.item,
             count(*) over (partition by user_id) as cnt
      from table1 t1 cross apply
           (values (t1.item_1), (t1.item_2), (t1.item_3)
           ) v(item)
      where v.item is not null
     ),
     t2 as (
      select t2.*, v.item,
             count(*) over (partition by role) as cnt
      from table2 t2 cross apply
           (values (t2.item_1), (t2.item_2), (t2.item_3)
           ) v(item)
      where v.item is not null
     )
select t1.user_id, t1.user_name, t2.role
from t1 join
     t2
     on t1.item = t2.item and t1.cnt = t2.cnt
group by t1.user_id, t1.user_name, t2.role, t1.cnt
having count(*) = t1.cnt;