Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 有没有一种方法可以让这个查询处理连接,或者我必须使用联合?_Sql_Sql Server - Fatal编程技术网

Sql 有没有一种方法可以让这个查询处理连接,或者我必须使用联合?

Sql 有没有一种方法可以让这个查询处理连接,或者我必须使用联合?,sql,sql-server,Sql,Sql Server,我可能正在尝试将联接用于此处不打算使用的目的 以下是我的(简化)表格结构: 表A 身份证 表C ID IsStatic(位) 表B 身份证 表A ID(可为空) 表C ID 表C 身份证 我的目标是将表B的所有行连接到表A的行,其中表B的表A ID列有一个值,并且等于表A的ID列值 我还需要表B的表A ID列没有值的所有表B行 我还需要表A的所有行,其中没有连接的表B行,并且表A的IsStatic列为true 表C还必须与表A或表B关联。如果表B没有TableAID的值,则Table

我可能正在尝试将联接用于此处不打算使用的目的

以下是我的(简化)表格结构:

表A

  • 身份证
  • 表C ID
  • IsStatic(位)
表B

  • 身份证
  • 表A ID(可为空)
  • 表C ID
表C

  • 身份证
我的目标是将表B的所有行连接到表A的行,其中表B的表A ID列有一个值,并且等于表A的ID列值

我还需要表B的表A ID列没有值的所有表B行

我还需要表A的所有行,其中没有连接的表B行,并且表A的IsStatic列为true

表C还必须与表A或表B关联。如果表B没有TableAID的值,则TableCID的值应等于TableC的ID值。否则,TableA的TableCID应该等于TableC的ID值

下面是一些SQL语句,用于创建一些表变量并填充示例数据:

DECLARE @TableA TABLE (TableAID int, TableCID int, IsStatic bit)
DECLARE @TableB TABLE (TableBID int, TableAID int, TableCID int)
DECLARE @TableC TABLE (TableCID int)

INSERT INTO @TableC (TableCID) VALUES (1)
INSERT INTO @TableC (TableCID) VALUES (2)

INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (1, 1, 0)
INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (2, 2, 1)
INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (3, 2, 1)
INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (4, 2, 0)

INSERT INTO @TableB (TableBID, TableAID, TableCID) VALUES (1, NULL, 1)
INSERT INTO @TableB (TableBID, TableAID, TableCID) VALUES (2, 1, 1)
INSERT INTO @TableB (TableBID, TableAID, TableCID) VALUES (3, 2, 2)
 select a.TableAID, b.TableBID
  from @TableA a
  full outer join @TableB b
    on b.TableAID = a.TableAID
 where b.TableBID is not null or a.IsStatic = 1
以下是我的(简化的)查询,它不太有效:

SELECT
    a.TableAID,
    b.TableBID
FROM @TableC c
LEFT OUTER JOIN @TableB b ON
    (b.TableAID IS NOT NULL OR (b.TableAID IS NULL AND b.TableCID = c.TableCID))
LEFT OUTER JOIN @TableA a ON
    a.TableCID = c.TableCID
    AND ((a.IsStatic = 1 AND b.TableBID IS NULL)
        OR (b.TableBID IS NOT NULL AND b.TableAID = a.TableAID))
使用sampel数据的查询结果为:

TableAID TableBID
-----------------
NULL     1
1        2
NULL     3       (not required)
NULL     2       (not required)
2        3
所需的结果是:

TableAID TableBID
-----------------
NULL     1
3        NULL     (missing)
2        3
1        2
此查询的问题是,如果TableB.TableAID没有值,则TableA.IsStatic为true且没有任何匹配TableB行的表A行将永远不包括在内。此外,还包括一些TableB行,它们不应该包括在内

我能看到的唯一其他方法是使用
联合
,而
不存在
,但我希望以更有效的方式来实现这一点

更新:添加WHERE子句会删除“not required”行,但仍会忽略缺少的行

WHERE (b.TableBID IS NULL OR b.TableAID IS NULL OR b.TableAID = a.TableAID)
与where子句相同的查询的结果为:

TableAID TableBID
-----------------
NULL     1
1        2
2        3

真是令人心烦意乱。我认为这是另一种表达方式。您必须查看性能是否良好:

select a.TableAID, b.TableBID
  from (select a.*
          from @TableA a
          join @TableC c
            on c.TableCID = a.TableCID) a
  full outer join (select b.*
                     from @TableB b
                     join @TableC c
                       on c.TableCID = b.TableCID) b
    on b.TableAID = a.TableAID
 where b.TableBID is not null or a.IsStatic = 1
我还应该提到,使用您提供的示例数据,很难确定上述查询是否真的符合您的要求。举例来说,如果我使用下面这个简单的查询来忽略
@TableC
表,那么我仍然可以用您的示例数据得到正确的结果:

DECLARE @TableA TABLE (TableAID int, TableCID int, IsStatic bit)
DECLARE @TableB TABLE (TableBID int, TableAID int, TableCID int)
DECLARE @TableC TABLE (TableCID int)

INSERT INTO @TableC (TableCID) VALUES (1)
INSERT INTO @TableC (TableCID) VALUES (2)

INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (1, 1, 0)
INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (2, 2, 1)
INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (3, 2, 1)
INSERT INTO @TableA (TableAID, TableCID, IsStatic) VALUES (4, 2, 0)

INSERT INTO @TableB (TableBID, TableAID, TableCID) VALUES (1, NULL, 1)
INSERT INTO @TableB (TableBID, TableAID, TableCID) VALUES (2, 1, 1)
INSERT INTO @TableB (TableBID, TableAID, TableCID) VALUES (3, 2, 2)
 select a.TableAID, b.TableBID
  from @TableA a
  full outer join @TableB b
    on b.TableAID = a.TableAID
 where b.TableBID is not null or a.IsStatic = 1
编辑:评论中关于OP“要求”解释的有趣讨论。。。但如果我必须回答安东的观点:

select a.TableAID, b.TableBID
  from (select a.*, 
               case when c.TableCID is not null then 1 end as has_c
          from @TableA a
          left join @TableC c
            on c.TableCID = a.TableCID) a
  full outer join (select b.*,
                          case when c.TableCID is not null then 1 end as has_c
                     from @TableB b
                     left join @TableC c
                       on c.TableCID = b.TableCID) b
    on b.TableAID = a.TableAID
 where (b.TableBID is not null or a.IsStatic = 1)
   and (a.has_c = 1 or b.has_c = 1)

在你的连接中,试试这个。ISNULL上的联接表(table.column“”)=ISNULL(otherTable.column“”)。请原谅我的格式。我在手机上。联接用于将列合并到一行中。您正在尝试将行合并到单个结果集中。这就是工会的宗旨。如果只使用union,您的查询将更易于维护和理解。“你有什么理由要避开它吗?”迈克害怕承诺!(开玩笑……联盟,明白吗?)说真的,我想我必须在我想要避免的查询中有一个低效的
不存在。但是安东的回答避免了这一点,我只是想看看这是否对我有效。johna,答案已经提供了,请检查并标记为接受,如果是您想要的。如果我们更改了样本数据,则此脚本似乎不正确。尝试将TableB值(2,1,1)的插入替换为未显示的值(2,1,3)@Anton,(2,1,3)无效,因为Table3没有示例行ID值3。(1,2)正在为我显示。请参见要求。如果表A中有对应的记录,则不应使用表B的CID。只有表A的CID@john,没有外键约束的要求,因此形式上3是有效的,并且可以出现在表B中。根据您的要求,如果我们有(3),我们应该显示(1,2),因为表A仍然与表C有有效链接。此答案非常有效。然而,我接受了@sstan的回答,因为执行计划和速度更好(更多地是由于真实的数据结构和索引)。非常感谢您的回答,我可以确认它与真实的结构和数据完美配合。