2014-07-08 53 views
0

首先,我對這個冗長且有點令人困惑的標題表示歉意,請允許我詳細說明。SQL Server如何選擇兩個結果集,第二組重疊第二個重疊

我有一個網上商店,銷售生日,聖誕節等卡,目前它提供了一個可供用戶選擇的默認卡的選擇。

我打算讓用戶修改現有的卡片(改變它的佈局,文字,着色等),但我想保留默認卡並記錄修改來自哪張卡。這部分我想我已經找到了。

我的目標是讓網站向用戶顯示所有默認卡片,但顯示用戶自己的替代卡片以代替它來自的默認卡片。

考慮到這一點,我的數據庫表有以下的局部佈局:

Table: Cards 
UserId int 
CardId int 
CardText int 

假設默認的卡都存儲在用戶ID 1,新用戶是用戶ID 2,針對上述表中的記錄會如下所示:

UserId CardId CardText 
    1  1 Valentines 
    1  2 Birthday 
    1  3 Merry Xmas 
    2  1 Be my valentine 

正如你所看到的,用戶#2已經修改卡#1改變從「情人節」的文字:「我的情人」和用戶#1,原卡#1仍然是可用爲未來的用戶。

我想顯示所有默認卡,但顯示用戶替換卡代替其默認配對卡。

這意味着用戶ID 1將看到:

CardId 1 [UserId #1] 
CardId 2 [UserId #1] 
CardId 3 [UserId #1] 

而且用戶ID 2將看到:

CardId 1 [UserId #2] <- 
CardId 2 [UserId #1] 
CardId 3 [UserId #1] 

我們的MSSQL。明顯的解決辦法是這樣的:

SELECT * FROM CARDS 
WHERE UserId = 1 
AND CardId NOT IN (SELECT CardId FROM CARDS WHERE UserId = 2) 
    UNION 
SELECT * FROM CARDS 
WHERE UserId = 2 

這將返回默認卡以及用戶#2修改卡。

我的問題是,是否有更有效的方法來做到這一點?我上面的代碼的問題是SQL代碼片段正在運行兩次(SELECT ... WHERE UserId = 2),這對我來說似乎效率低下。

我看過其他集合運算符沒有成功(INTERSECT,EXCEPT),我甚至樂於使用MERGE運算符的想法無濟於事。

謝謝你的幫助。

+0

SQL數據沒有任何順序,除了由'order by'子句指定的順序之外。你在點什麼? – podiluska

+1

如何解決父卡ID指向原卡而原卡無效? –

回答

1

您可以使用CTE和ROW_NUMBER函數爲記錄(具有相同CardID的記錄分組)分配一個行號(「優先級」),然後僅選擇具有最高優先級(優先級= 1)的記錄:

WITH cte AS 
(
    SELECT 
     CardID, 
     UserID, 
     CardText, 
     priority = ROW_NUMBER() OVER (PARTITION BY CardID ORDER BY UserID DESC) 
    FROM 
     dbo.Cards 
    WHERE 
     UserID IN (1,2) -- filter by UserIDs of a user (UserID=2 in this example) and a "dummy user" that holds default values (UserID=1) 
) 

SELECT * FROM cte WHERE priority=1 

編輯:這假定該「僞」用戶的用戶ID是總是比實際用戶的用戶ID(例如,「虛擬」用戶的用戶ID爲1,實際的用戶ID> 1)。

+0

這是完美的!正是我所尋找的,你的先生是上帝! – user328414

相關問題