【问题标题】:Tricky join based on results of an aggregate evaluation基于聚合评估结果的棘手连接
【发布时间】:2010-12-23 07:29:11
【问题描述】:

在 SQL Server 2008 中,我有 3 个表:Definitions、Params 和 Items。第一个表包含一个参数可能是的最小值和最大值。参数包含针对给定定义的 0 个或多个参数,用于项目。我希望通过执行适当的条件连接/评估来获得有效的项目 ID。

举例说明:

将返回 ItemID = 1,因为 Params 中没有任何内容违反 Definitions.Min|Max。

不会返回 ItemsID = 2,因为 Hi = 103 违反了 DefID = 2 的 Definitions.Max。鉴于此,最后一个条目违反 Definitions.Low 的事实无关紧要,但为了清楚说明而显示。

ItemID = 3 将匹配,因为它有一个在范围内的 Param。无需加入所有定义。

【问题讨论】:

    标签: sql-server join filtering aggregate


    【解决方案1】:

    怎么样

    SELECT  *
    FORM    Items i INNER JOIN
            Params p    ON  i.ItemID = p.ItemID INNER JOIN
            Definitions d   ON  p.DefinationID = d.DEfinationID
    WHERE   p.Hi <= d.Max
    AND         p.Low >= d.Min
    

    编辑

    看看这个完整的例子

    DECLARE @Items TABLE(
            ItemID INT
    )
    DECLARE @Params TABLE(
            DefID INT,
            ItemID INT,
            Low FLOAT,
            Hi FLOAT
    )
    DECLARE @Defs TABLE(
            DefID INT,
            [Min] FLOAT,
            [Max] FLOAT
    )
    
    INSERT INTO @Items SELECT 1
    INSERT INTO @Items SELECT 2
    INSERT INTO @Items SELECT 3
    
    INSERT INTO @Params SELECT 1, 1, 11, 18
    INSERT INTO @Params SELECT 1, 1, 13, 17
    INSERT INTO @Params SELECT 2, 1, 25, 80
    
    INSERT INTO @Params SELECT 1, 2, 12, 15
    INSERT INTO @Params SELECT 1, 2, 14, 15
    INSERT INTO @Params SELECT 2, 2, 50, 80
    INSERT INTO @Params SELECT 2, 2, 50, 103
    INSERT INTO @Params SELECT 2, 2, 10, 80
    
    INSERT INTO @Params SELECT 2, 3, 24, 60
    
    INSERT INTO @Defs SELECT 1, 10, 20
    INSERT INTO @Defs SELECT 2, 20, 100
    
    ;WITH InvalidValues AS (
            SELECT  DISTINCT
                    i.ItemID
            FROM    @Items i INNER JOIN
                    @Params p   ON  i.ItemID = p.ItemID INNER JOIN
                    @Defs d ON  p.DefID = d.DefID
            WHERE   p.Low < d.[Min]
            OR      p.Hi > d.[Max]
    )
    SELECT  *
    FROM    @Items i 
    WHERE   NOT EXISTS  (
                            SELECT  1
                            FROM    InvalidValues
                            WHERE   ItemID = i.ItemID
                        )
    AND     EXISTS  (
                        SELECT  1
                        FROM    @Params p
                        WHERE   ItemID = i.ItemID
                    )
    

    结果

    ItemID
    1
    3
    

    【讨论】:

    • @astander 谢谢 - 但我希望它是那么简单。运行这个给我 4 * ID = 1 (在我的数据测试用例中)。如果我将 1 个参数抛出边界,那么我只会得到 3 * ID = 1。当然我需要 0 * ID = 1。
    • 好的,所以如果在任何阶段para超出范围,您希望排除该项目?
    • 100%。您已经启发了可能的答案:计算“范围内”,使用交叉应用来计算“全部”,并且只获取两个 # 为 = 的记录。但是,为了速度,我希望它不要不必要地加入(我们正在谈论数百万条记录)。
    • 附言。我投了一个 EXCEPT 而不是 CTE :)
    • 我刚刚意识到我不能只说“SELECT * FROM Items”......它必须只返回连接的值。
    猜你喜欢
    • 1970-01-01
    • 2017-08-20
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多