2017-04-14 86 views
-1

我有一個視圖,我需要提供羣集索引問題是爲了提供羣集索引它不應該有任何的左或右外連接,我想用INNER連接替換LEFT外連接,我能想到的一種方法是在正確的表格中插入一個虛擬值,讓我們說-1,即使左邊表中的所有ID都不匹配INNER JOIN中右邊的表中的Ids,但由於我們已經在右表中插入-1,我們使用IsNULL(u.UserId,-1)它應該返回左表中的所有值,但不知何故,這種方法不起作用。如何用SQL中的INNER連接替換LEFT外部連接?

create table Users(
UserId int, 
UserName nvarchar(255) 
) 
insert into Users values(1,'sid429') 
insert into Users values(2,'ru654') 
insert into Users values(3,'dick231') 

create table managers 
(
caseId int, 
CaseName nvarchar(255), 
UserId int 
) 

insert into managers values (100,'Case1',1) 
insert into managers values (101,'Case2',2) 
insert into managers values (-1,NULL,-1) 


select username from users u inner join managers m on m.UserId=IsNULL(u.UserId,-1) 
+0

請參閱英文散文中的「句子」和「句點」。然後使用它們。 – philipxy

+0

@philipxythank你非常想糾正我的語法,而不是提供一個解決方案我相信你已經理解了整個問題,即使是上面寫的語句。 –

+0

你的語法不是問題。你不清楚。請閱讀並執行[mvce]。 – philipxy

回答

0

不要談指標,但我認爲你可以取代LEFT JOIN通過INNER JOIN + UNION

select username from users u inner join managers m on m.UserId= u.UserId 

UNION ALL 

select username from users u WHERE NOT EXISTS (SELECT 1 FROM managers m WHERE m.UserId = u.UserId) 
1

ISNULL(u.UserId,-1)看起來不正確 - u.UserId從不爲空,因爲缺少數據在管理器表中 - 在這種情況下,u.UserId將始終有一個值,但m.UserId可能不會,所以IsNull(u.UserId,-1)將不起作用。

我很想看到更好的答案,但我不認爲你可以這樣做 - 我想你最終需要有條件地將值替換爲-1,如果它不存在於另一個表中,就像這樣的:

select username from users u 
inner join managers m on m.UserId = 
    case when not exists(select * from managers where UserId = u.UserId) 
    then -1 else u.UserId end 

這有預期的效果,但看着執行計劃,也不會幫助你的性能問題。

0

如果在相關表中添加缺失值,則可以用INNER JOIN替換LEFT OUTER JOIN。

它不適合你,因爲你已經添加了-1值。但是,INNER JOIN上的不匹配值是3,而不是null或-1。

您可以在運行時與UNION,無需創建永久,你試圖做這些值做到這一點(即插入值-1):

with expanded_managers as (
    select CaseId, CaseName, UserId 
    from managers 
    union 
    select null, null, UserId 
    from users 
    where not exists (select * from managers where managers.UserId = users.UserId) 
) 

select UserName, CaseName 
from users 
    inner join expanded_managers on expanded_managers.UserId = users.UserId 
0

如果只要求用戶名應該是簡單: 從用戶中選擇不同的用戶名u內部連接管理器m上m.UserId = u.UserId OR(m.UserId = -1 AND u.userId = u.userId)

0

我已經清理了這部分位。我不得不猜測邏輯模型,因爲你沒有指定任何約束

create table Users (
    UserId int   not null 
, UserName nvarchar(255) not null 

, constraint pk_users primary key (UserId) 
, constraint ak_users unique  (UserName) 
); 


create table Cases (
    CaseId int   not null 
, CaseName nvarchar(255) not null 
, UserId int   not null 

, constraint pk_cases primary key (CaseId) 
, constraint ak_cases unique  (CaseName) 
, constraint fk_cases foreign key (UserId) 
       references Users (UserId) 
); 

insert into Users values(1,'sid429') ; 
insert into Users values(2,'ru654') ; 
insert into Users values(3,'dick231'); 

insert into Cases values (100,'Case1',1); 
insert into Cases values (101,'Case2',2); 

這主要是不言自明的,但你必須瞭解的結果是候選鍵(唯一的)是:{UserID, CaseId}{UserName, CaseName}{UserID, CaseName}{UserName, CaseId}。不知道你是否期待這一點。

with 
R_00 as (
    select UserId from Users 
    except 
    select UserId from Cases 
) 
select u.UserId 
    , u.UserName 
    , c.CaseId 
    , c.CaseName  
from Users as u 
join Cases as c on u.UserId = c.UserId 

union 

select u.UserId 
    , u.UserName 
    , (-1) as CaseId 
    , 'n/a'as CaseName 
from Users as u 
join R_00 as r on r.UserId = u.UserID 
; 

這一點,類似於在後其他例子另一個版本。

select u.UserId 
    , u.UserName 
    , c.CaseId 
    , c.CaseName  
from Users as u 
join Cases as c on u.UserId = c.UserId 

union 

select u.UserId 
    , u.UserName 
    , (-1) as CaseId 
    , 'n/a' as CaseName 
from Users as u 
where not exists (select 1 from Cases as c where c.UserId = u.userId) 
;