【问题标题】:SQL Join but return rows based on criteria or order of preferenceSQL 联接但根据条件或优先顺序返回行
【发布时间】:2014-05-25 19:02:29
【问题描述】:

我使用 Microsoft SQL Server 连接两个表。表 1 中的一行可能与表 2 中的几行相关。理想情况下,我希望根据存在的数据和某些标准从表 2 中恢复一行

表 2 有一个 ID 和一个日期时间字段。 我一直只带回日期时间为 NULL 的值,但尽管它们是有效的,但它不必要地排除了日期时间仍在未来的时间。

我希望能够从表 2 中恢复一行,如果日期时间字段在未来,则该行优先于具有 NULL 值的行。如果将来没有带有日期时间的连接行,它将返回 NULL 值行

我认为我需要某种形式的子查询或对存在的行进行评分并带回最高值的东西,但我不确定。

无论采用何种方法,在此查询中都会使用此逻辑的许多类似情况。

【问题讨论】:

    标签: sql select join subquery correlated-subquery


    【解决方案1】:

    如果我说得对,您想从 Table2 中获取日期时间字段为空或将来有值的行。你说你希望未来的日期优先于 NULL 值,所以我知道你想要一个最大值。让我们设置一些示例数据:

    CREATE TABLE Table1 (id_table1 int not null primary key)
    
    INSERT INTO Table1 (id_table1)
    VALUES (1)
    INSERT INTO Table1 (id_table1)
    VALUES (2)
    INSERT INTO Table1 (id_table1)
    VALUES (3)
    INSERT INTO Table1 (id_table1)
    VALUES (4)
    INSERT INTO Table1 (id_table1)
    VALUES (5)
    
    
    CREATE TABLE Table2 (id_table2 int not null primary key, id_table1 int, date_value datetime)
    
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (1,1,'2001-01-01 00:00:00')
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (2,1,NULL)
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (3,1,'2015-01-01 00:00:00')
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (4,2, '2002-01-01 00:00:00')
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (5,3, '2003-01-01 00:00:00')
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (6,3, '2018-01-01 00:00:00')
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (7,4, '2004-01-01 00:00:00')
    INSERT INTO Table2 (id_table2,id_table1,date_value)
    VALUES (8,4,NULL)
    

    现在 Table2 中每个 id_table1 都有 0..n 行。

    首先,您可以从 Table2 中获取符合条件 NULL 或将来的所有行:

    declare @datThreshold datetime
    set @datThreshold=getdate()
    
    SELECT *
    FROM Table2 t2
    WHERE t2.date_value is null OR t2.date_value>@datThreshold
    

    正如我所说,我了解您希望 NULL 最低的剩余日期的最大值。您可以通过将 NULL 值设置为默认值来实现这一点,默认值可以是 @datThreshold,因为由于 WHERE 条件,这将是最低值。

    declare @datThreshold datetime
    set @datThreshold=getdate()
    
    SELECT id_table1, max(isnull(t2.date_value,@datThreshold)) max_date
    FROM Table2 t2
    WHERE t2.date_value is null OR t2.date_value>@datThreshold
    GROUP BY t2.id_table1
    

    现在每个 id_table1 都有一行,并且必须将其加入 Table1:

    declare @datThreshold datetime
    set @datThreshold=getdate()
    
    SELECT t1.id_table1,max.id_table1,max.max_date
    FROM Table1 t1
        JOIN (SELECT id_table1, max(isnull(t2.date_value,@datThreshold)) max_date
            FROM Table2 t2
            WHERE t2.date_value is null OR t2.date_value>@datThreshold
            GROUP BY t2.id_table1) max ON t1.id_table1=max.id_table1
    

    您也可以再次将默认日期替换为 NULL:

    declare @datThreshold datetime
    set @datThreshold=getdate()
    
    SELECT t1.id_table1,max.id_table1,case max.max_date when @datThreshold then NULL else max.max_date end date_value
    FROM Table1 t1
        JOIN (SELECT id_table1, max(isnull(t2.date_value,@datThreshold)) max_date
            FROM Table2 t2
            WHERE t2.date_value is null OR t2.date_value>@datThreshold
            GROUP BY t2.id_table1) max ON t1.id_table1=max.id_table1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      • 2012-05-12
      • 2021-10-08
      • 1970-01-01
      相关资源
      最近更新 更多