【问题标题】:SQL subquery confusion: how to refer to outer query column in the SAME tableSQL子查询混淆:如何引用SAME表中的外部查询列
【发布时间】:2016-03-10 17:54:26
【问题描述】:

我对 SQL 还很陌生。我试图通过手动调整 SQL 在 Business Objects 中构造某个查询。我对子查询有一个初学者的理解,但是有一个特殊的问题让我难以理解。我将尝试使用代码示例进行解释:

SELECT
TBL1.ID
TBL1.Field1text
TBL1.Field2date
CASE WHEN
    (
    TBL1.Field1text = 'ValueTwo'
    AND
    TBL1.Field2date >= '30/11/2014'
    /* Arbitrary date. I actually want this to be, for example,
        "TBL1.Field2date minus 2 months where TBL1.ID is the same, and
        TBL1.Field1text is ValueOne" */
    )
THEN 'Match'
ELSE 'No Match'
END
As CutomColumnNameToShowMatches
WHERE
TBL1.Field1text = 'ValueOne'
AND
TBL1.Field2date BETWEEN '01/01/2015' AND '31/12/2015'

如您所见,我在选择条件中使用了 CASE WHEN 子句来返回一个自定义字段,该字段显示是否存在匹配项(如下所述)。

源表有一堆记录,其中 Field1text 的每个值都与特定日期 (Field2date) 相关联。 “ID”字段不是主键。可以跨多个记录使用相同的 ID。例如,ID 52 可能有多个记录,它们都显示不同的 Field1text 值及其关联的 Field2date。跟我到现在?很好。

我的基本查询返回 Field1text 为“ValueOne”的记录列表。这很容易。但是,我接下来要做的是确定 - 对于每条记录:

"取ID号,查表,看同一个IDALSO是否有Field1text等于ValueTwo的记录,且该ValueTwo记录的Field2date在Field2date的2个月内ValueOne 记录”。如果是,则返回匹配。如果不是,则不返回匹配项。

这一切都有意义吗?如果需要,请让我澄清一下。

到目前为止,我的研究表明某种 JOIN 可能是答案:但是我不确定这将如何应用于这种情况,或者即使它是正确的方法。

上面的代码运行良好,但仅在子查询中指定了日期。我需要一种方法来使该日期可变,并链接到相同 ID 的 ValueOne 记录中的日期。

请注意,我们都是在同一张桌子上工作的。此外,当我在 Business Objects 中工作时,我无法像在 MS Access 中那样创建和保存命名查询。一切都必须从一段 SQL 代码中运行。

感谢您的帮助! :)

【问题讨论】:

  • FROM 子句会有所帮助。
  • 了解实际的 PK 也会有所帮助。
  • 另外:您的意思是“两个月内”还是“60 天内”?语义非常不同,因为 12 月 31 日 在 10 月 1 日之后的两个月内,尽管晚了 91 天。
  • 糟糕 - 是的,我在重新输入的示例中忘记了 FROM 子句 :) 不过这个问题并不重要:假设 FROM TBL1。是的,我知道 2 个月与 60 天不同 - 但这只是一个例子。

标签: sql join subquery business-objects


【解决方案1】:

为同一个表分配不同的别名并将两个别名连接在一起。使用您的示例,我创建了一个查询,该查询仅显示在时间范围内匹配的行。它使用别名“a”和“b”,如下所示:

SELECT
    a.ID,
    a.Field1text,
    a.Field2date
FROM
    TBL1 AS a
    INNER JOIN TBL1 AS b ON 
        a.ID = b.ID 
        AND a.Field1text = b.Field1text
        AND b.Field2date > a.Field2date 
        AND b.Field2date <= DATEADD(month, 2, a.Field2date )

或者,如果您想要 'a' 中的所有行,并且只需要在 'b' 中找到匹配项的指示符,请尝试以下操作:

SELECT
    a.ID,
    a.Field1text,
    a.Field2date,
    CASE 
        WHEN 
            (
                SELECT TOP 1 
                    CASE WHEN b.ID IS NULL THEN 'No Match' ELSE 'Match' END
                FROM 
                    TBL1 AS b
                WHERE
                    a.ID = b.ID 
                    AND a.Field1text = b.Field1text
                    AND b.Field2date > a.Field2date 
                    AND b.Field2date <= DATEADD(month, 2, a.Field2date )
            ) IS NULL 
        THEN 'No Match' 
        ELSE 'Match' 
    END AS [MatchSearch]
FROM
    TBL1 AS a
WHERE
    a.Field1text = 'ValueOne'
    AND a.Field2date BETWEEN '01/01/2015' AND '12/31/2015'

注意:这仍将显示“b”中与外部 WHERE 子句匹配的行。如果您不想显示它们,请考虑添加 GROUP BY 子句。

PS:我找不到您查询的 FROM 部分,所以我做了一个。 此外,您的日期范围文本格式不正确:'31/12/2015'

【讨论】:

  • 唐 - 看起来你正在做某事。我不知道有人可以在 SQL 运行时为表分配别名(告诉你我是一个 n00b)。我明天会试试这个,如果它有效,请告诉你 - 谢谢!
  • 唐,它有效!太感谢了。我不得不稍微修改您的示例,但是为表分配别名的原则很棒。顺便说一句 - 我的日期在国际上格式正确。我不是美国人!不幸的是,许多美国服务器会更改日期,所以我倾向于使用 31-dec-2015 来确保不会发生这种情况:)
  • 太棒了,抱歉日期混淆了,我的服务器出错了。我很高兴它对你有用。
猜你喜欢
  • 2022-01-26
  • 1970-01-01
  • 2010-09-30
  • 1970-01-01
  • 2012-11-09
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多