不知道如何加入这两个表

时间:2010-07-26 19:17:17

标签: sql sql-server tsql join

我无法想出这个问题的标题,因为我不确定如何做我想要的,所以我不确定“加入”是否是这个例子中最好的术语。

我的数据库中有两个表,计划和假设如下所示:

计划表

Plankey  ass1 ass2 ass3 ass4
aplan    0    6    5    7
bplan    2    0    7    4

假设表

assType refKey assName
"ass1"  0      "gender factors a"
"ass1"  2      "gender factors b"
"ass2"  0      "age factors a"
"ass2"  6      "age factors b"
"ass3"  5      "inflation factors a"
"ass3"  7      "inflation factors b"
"ass4"  4      "tax factors a"
"ass4"  7      "tax factors b"

我需要创建一个查询(或一组查询和子查询),它为我提供每个计划使用的假设的名称:

Plankey  assName1           assName2         assName3               assName4
aplan    "gender factors a" "age factors b"  "inflation factors a"  "tax factors b"
bplan    "gender factors b" "age factors a"  "inflation factors b"  "tax factors a"
是的......我知道。 assName。此外,即使这不是最好的设计,这是我无法控制的。我只是想查询一组现有数据。

我还应该提到有超过500种假设类型(ass1,ass2,...,ass500等),每种类型每种假设类型可以有超过100种假设的refKey / Name。

我试图绕过这个并且看起来很容易,但我无法弄清楚如何做到这一点。有任何想法吗?也许有一个我失踪的概念,因为我还没有遇到它。我可以将列名称assName1,assName2等硬编码到我的查询中,但即使这样,我也不确定如何从Assumptions表中“查找”assNames,因为我似乎正在从同一个表中查找多个我的结果中的列。

编辑:我省略了一些非常重要的事情。 refkey在假设表中重复使用。因此assName由assType和refKey的组合唯一确定。我为在我的例子中没有说清楚而道歉!在我查看答案之前,我忘记了这一点。我已经改变了我的例子以反映这一点。

EDIT2:我正在使用MS SQL Server。

EDIT3:我希望在每个计划的假设表中找到匹配。如果没有,我会遇到更大的问题 - 与此问题无关。

5 个答案:

答案 0 :(得分:6)

对于ASSUMPTIONS表格中的每个ass#列,您必须左键加入PLANS表:

   SELECT p.plankey,
          a1.assname,
          a2.assname,
          a3.assname,
          a4.assname
     FROM PLANS p
LEFT JOIN ASSUMPTIONS a1 ON a1.refkey = p.ass1
                        AND a1.asstype = 'ass1'
LEFT JOIN ASSUMPTIONS a2 ON a2.refkey = p.ass2
                        AND a2.asstype = 'ass2'
LEFT JOIN ASSUMPTIONS a3 ON a3.refkey = p.ass3
                        AND a3.asstype = 'ass3'
LEFT JOIN ASSUMPTIONS a4 ON a4.refkey = p.ass4
                        AND a4.asstype = 'ass4'

在不知道数据库的情况下,我无法提供动态SQL的语法来构造需要执行的不同数量的连接的查询。

答案 1 :(得分:1)

SELECT p.PlanKey, a1.name, a2.name, a3.name, a4.name
FROM Plans AS p
LEFT JOIN Assumptions AS a1 ON p.ass1 = a1.refKey
LEFT JOIN Assumptions AS a2 ON p.ass2 = a2.refKey
LEFT JOIN Assumptions AS a3 ON p.ass3 = a3.refKey
LEFT JOIN Assumptions AS a4 ON p.ass4 = a4.refKey

答案 2 :(得分:1)

这在编程语言中非常简单。您将阅读整个Assumptions表,然后阅读Plans表,将assName替换为每个Plans行中的四个refKeys。

当我编辑这个答案时,OMG Ponies有最流行的SQL答案。

答案 3 :(得分:1)

处理此问题的最佳方法是将您的assName *列转换为子查询中的行或第二个表中的视图。

如果您使用的是SQL Server,则可以使用UNPIVOT来执行此操作。我不确定其他DBMS支持UNPIVOT,所以让我们知道你正在使用哪一个。如果您使用的是SQL Server,我将提供一个示例。

http://msdn.microsoft.com/en-us/library/ms177410.aspx

<强>更新

这是一个查询,它将Plans表转换为易于加入的表单。但是,我忽略了这样一个事实:你想要的结果仍然是“旋转”的,所以除非你能以更“标准化”的形式接受查询结果,否则它不会有多大用处。对于'枢轴'结果,其他建议要好得多。

无论如何,这是对任何有兴趣的人的查询:

SELECT [PVT].[PlanKey], [PVT].[RefKey], [PVT].[Ass]
FROM   [Plans] [P]
       UNPIVOT
       ([RefKey] FOR [Ass] IN ([ass1], [ass2], [ass3], [ass4])) [PVT]

道歉,如果它没有任何用处 - 我的错误。

答案 4 :(得分:1)

您可以尝试将Plans表规范化为内联查询,然后加入该表。我不知道哪个会更糟 - 500个工会或500个联盟。

SELECT
    SQ.Plankey,
    A.assName
FROM
(

    SELECT Plankey, ass1 AS assRefKey, 'ass1' AS assType FROM Plans WHERE ass1 IS NOT NULL UNION ALL
    SELECT Plankey, ass2, 'ass2' AS assType FROM Plans WHERE ass2 IS NOT NULL UNION ALL
    ...
    SELECT Plankey, ass500, 'ass500' AS assType FROM Plans WHERE ass500 IS NOT NULL
) SQ
INNER JOIN Assumptions A ON
    A.refKey = SQ.assRefKey AND
    A.assType = SQ.assType

结果集不是您请求的格式,但对于某些数据使用可能更好。无论哪种方式,这是一个丑陋的数据库设计。你认为,当他们达到ass100时,他们会意识到他们可能会做错事。

如果您要使用此方法,您可能只想为该内部查询创建一个视图并对该视图进行查询。