我有2个表j和c。
两个表都有port和sec列。
对于j.port = ABC,我想将c.sec的前6个字符与j.sec的前6个字符连接起来。
对于其他j.port,我想加入c.sec = j.sec
我该怎么做?
select c.port,j.port,c.sec,j.sec from j, c
where c.SEC =
CASE WHEN j.port = 'ABC' then SUBSTRING(c.sec,1,6) = SUBSTRING(j.sec,1,6)
--> something like this
else j.sec
答案 0 :(得分:1)
将性能明智地分成两部分可能是有益的。复杂的连接条件将强制嵌套循环。
SELECT c.port,
j.port,
c.sec,
j.sec
FROM j
JOIN c
ON LEFT(c.sec, 6) = LEFT(j.sec, 6)
WHERE j.port = 'ABC'
UNION ALL
SELECT c.port,
j.port,
c.sec,
j.sec
FROM j
JOIN c
ON c.sec = j.sec
WHERE j.port IS NULL
OR j.port <> 'ABC'
或者在这种情况下,您也可以
SELECT c.port,
j.port,
c.sec,
j.sec
FROM j
JOIN c
ON LEFT(c.sec, 6) = LEFT(j.sec, 6)
and (j.port = 'ABC' OR c.sec = j.sec)
这使主联接成为简单的等值联接,可以使用任何联接算法,并对结果使用残差谓词。
对于下面的示例数据,这两个数据在我的计算机上都花费了大约700毫秒,而我又在30秒后杀死了三个竞争答案,因为它们都没有在那段时间内完成。
create table c(port varchar(10), sec varchar(10) index ix clustered )
create table j(port varchar(10), sec varchar(10))
INSERT INTO c
SELECT TOP 1000000 LEFT(NEWID(),10) , LEFT(NEWID(),10)
FROM sys.all_objects o1, sys.all_objects o2
INSERT INTO j
SELECT TOP 1000000 LEFT(NEWID(),10) , LEFT(NEWID(),10)
FROM sys.all_objects o1, sys.all_objects o2
答案 1 :(得分:0)
您可以使用:
select c.port,j.port,c.sec,j.sec
from j
join c
on (CASE WHEN j.port = 'ABC' and SUBSTRING(c.sec,1,6) = SUBSTRING(j.sec,1,6) then 1
WHEN c.sec = j.sec THEN 1
END) = 1
与:
select c.port,j.port,c.sec,j.sec
from j
join c
on (j.port = 'ABC' and SUBSTRING(c.sec,1,6) = SUBSTRING(j.sec,1,6))
or (c.SEC = j.sec AND (j.port <> 'ABC' or j.port IS NULL))