带负片的sql join问题

时间:2009-07-20 14:05:24

标签: c# sql sqlclr

我需要使用连接从两个表中选择数据。这很简单,在这里没有问题。当我加入的字段被用作两个单独的外键时(我没有设计这个),就会出现问题。因此,我加入的ID字段是正数或负数。

如果它是一个正数,它与table_2表上的ID_1相关,如果它是负数,则该数字与table_2表上的ID_2相关。然而,ID_2将是一个正数(即使它在外键中存储为负数)。显然没有限制来强制执行这些 - 所以本质上不是真正的外键:/

我正在使用的SQL就是这样的,对于正数来说很好:

select t1.Stuff, t2.MoreStuff from table_1 t1
join table_2 t2 on t1.ID_1 = t2.ID_1
where ...

如何将此消极方面纳入联接。这甚至可能吗?理想情况下,我想根据我的需要改变表格,但显然这不是一个有效的选择。我很好,真的卡住了。

我唯一的另一个想法就是使用单独的sql语句来处理这些奇怪的问题。这一切都是由来自C#的clr sql运行的。在代码中添加单独的SqlCommand很可能会减慢速度,因此我更倾向于将它全部保存在一个命令中。

欢迎您提出意见,谢谢:)

8 个答案:

答案 0 :(得分:2)

最简单的方法 - 使用UNION ALL连接这些表:

select t1.Stuff, t2.MoreStuff from table_1 t1
join table_2 t2 on t1.ID_1 = t2.ID_1
where t1._ID_1>0
UNION ALL
select t1.Stuff, t2.MoreStuff from table_1 t1
join table_2 t2 on abs(t1.ID_1) = t2.ID_2
where t1._ID_1<0

答案 1 :(得分:2)

假设表格如下:

Table1 (id INT, foo INT, fk INT)

Table2 (id1 INT, id2 INT, bar VARCHAR(100))

... fk可以Table2使用id1查找一行,如果是肯定的话id2,如果是肯定的话。

然后你可以按如下方式进行连接:

SELECT T1.id, T1.foo, T2.bar
FROM Table1 T1 INNER JOIN Table2 T2
ON    (T1.fk > 0 AND T2.id1 = T1.fk)
   OR (T1.fk < 0 AND T2.id2 = - T1.fk)

答案 2 :(得分:1)

这不会很有效......但是,什么都不会。您需要将否定键转换为正键,并将条件逻辑转换为连接。像这样:

select t1.Stuff, t2.MoreStuff 
from table_1 t1
join table_2 t2 on (t1.ID_1 > 0 AND t1.ID_1 = t2.ID_1)
  OR (t1.ID_1 <0 AND ABS(t1.ID_1) = t2.ID_2)
where ...

没有机会使用索引,因为你正在转换t1.ID_1(使用ABS功能),但鉴于这种情况,你可以做到最好。

答案 3 :(得分:1)

您可以执行类似的操作,但只有在将架构设计器引入LART后才能执行此操作:

SELECT
    t1.stuff, COALESCE(t2a.morestuff, t2b.morestuff)
  FROM
    table_1 t1
    LEFT JOIN table_2 t2a ON (t1.id_1 > 0 AND t1.id_1 = t2a.id_1)
    LEFT JOIN table_2 t2b ON (t1.id_1 < 0 AND t1.id_1 = -1 * t2b.id_2)
  // etc

可替换地,

SELECT
    t1.stuff, t2.morestuff
  FROM
    table_1 t1
    LEFT JOIN table_2 t2 ON (
      (t1.id_1 > 0 AND t1.id_1 = t2.id_1)
      OR (t1.id_1 < 0 AND t1.id_1 = -1 * t2.id_2)
    )
  // etc

记住LART,这是最重要的部分!

答案 4 :(得分:1)

试试这个

DECLARE @Table TABLE(
        ID INT,
        ForeignKeyID INT
)

INSERT INTO @Table (ID,ForeignKeyID) SELECT 1, 1
INSERT INTO @Table (ID,ForeignKeyID) SELECT 2, 2
INSERT INTO @Table (ID,ForeignKeyID) SELECT 3, -1
INSERT INTO @Table (ID,ForeignKeyID) SELECT 4, -2

DECLARE @ForeignTable TABLE(
        ID_1 INT,
        ID_2 INT,
        Val VARCHAR(MAX)
)

INSERT INTO @ForeignTable (ID_1,ID_2,Val) SELECT 1, 11, '1'
INSERT INTO @ForeignTable (ID_1,ID_2,Val) SELECT 2, 22, '2'
INSERT INTO @ForeignTable (ID_1,ID_2,Val) SELECT 3, 1, '3'
INSERT INTO @ForeignTable (ID_1,ID_2,Val) SELECT 3, 2, '4'

SELECT  *
FROM    @Table t INNER JOIN
        @ForeignTable ft ON ABS(t.ForeignKeyID) =
                            CASE 
                                WHEN t.ForeignKeyID > 0
                                    THEN ft.ID_1
                                ELSE
                                    ft.ID_2
                            END

答案 5 :(得分:0)

必须是

之类的东西
select t1.Stuff, t2.MoreStuff from table_1 t1, table_2 t2 where (t1.ID_1 = t2.ID_1 OR t1.ID_1 = CONCAT("-",t2.ID_1)) where ...

不确定我是否误解了你的问题。

答案 6 :(得分:0)

通过在表2中应用左连接并使用绝对值函数,您应该能够完成您正在寻找的内容:

SELECT t1.Stuff, isnull(t2.MoreStuff, t2_2.MoreStuff) 
FROM table_1 t1
    LEFT JOIN table_2 t2     ON t1.ID_1 = t2.ID_1 
                             AND t1.ID_1 > 0
    LEFT JOIN table_2 t2_2   ON abs(t1.ID_2) = t2_2.ID_2 
                             AND t1.ID_2 < 0
WHERE 
   ...

这里需要注意的是,如果ID_1ID_2不相互排斥,您将获得2个查询结果。

答案 7 :(得分:0)

select t1.Stuff, t2.MoreStuff from table_1 t1
join table_2 t2 on t1.ID_1 = t2.ID_1 or -t1.ID_1 = t2.ID_2
where ...