2014-06-29 143 views
0

我在編寫SQL查詢時遇到困難。這是3個表的結構,表Race_ClassificationType是多對多表。SQL多對多關係

Table Race 
---------------------------- 
RaceID 
Name 

Table Race_ClassificationType 
---------------------------- 
Race_ClassificationTypeID 
RaceID 
RaceClassificationID 

Table RaceClassificationType 
---------------------------- 
RaceClassificationTypeID 
Name 

我想要做的就是與某些類別的比賽。

CREATE TYPE [dbo].[RaceClassificationTypeTable] 
AS TABLE 
(
    RaceClassificationTypeID INT NULL 
); 
GO 

CREATE PROCEDURE USP_GetRaceList 
    (@RaceClassificationTypeTable AS [RaceClassificationTypeTable] READONLY, 
    @RaceTypeID INT = NULL, 
    @IsCompleted BIT = NULL, 
    @MinDateTime DATETIME = NULL, 
    @MaxDateTime DATETIME = NULL, 
    @MaxRaces INT = NULL) 
    WITH RECOMPILE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    SELECT DISTINCT 
      R.[RaceID] 
      ,R.[RaceTypeID] 
      ,R.[Name] 
      ,R.[Abbreviation] 
      ,R.[DateTime] 
      ,R.[IsCompleted] 
    FROM [Race] R,[Race_ClassificationType] R_CT, [RaceClassificationType] RCT 
    WHERE (R.[RaceTypeID] = @RaceTypeID OR @RaceTypeID IS NULL) 
    AND  (R.[IsCompleted] = @IsCompleted OR @IsCompleted IS NULL) 
    AND  (R.[DateTime] >= @MinDateTime OR @MinDateTime IS NULL) 
    AND  (R.[DateTime] <= @MaxDateTime OR @MaxDateTime IS NULL) 
    AND  (R.RaceID = R_CT.RaceID) 
    AND  (R_CT.RaceClassificationTypeID = RCT.RaceClassificationTypeID) 
    AND  (RCT.RaceClassificationTypeID IN (SELECT DISTINCT T.RaceClassificationTypeID FROM @RaceClassificationTypeTable T)) 
    ORDER BY [DateTime] DESC 
    OFFSET 0 ROWS FETCH NEXT @MaxRaces ROWS ONLY 
END 
GO 

由於它是該存儲過程犯規正確地工作,因爲它返回具有至少一個分類類型ID所有種族:結果是由具有保持所期望的分類的表值參數存儲過程返回在分類類型ID的表值參數中(由於IN子句)。我希望存儲過程僅返回具有表值參數中提供的所有分類的種族。

實施例:在RaceClassificationTypeTable參數

RaceClassificationTypeID RaceID 
3 92728 
3 92729 
8 92729 
29 92729 
12 92729 
2 92729 
3 92730 
8 92730 
8 92731 
1 92731 

RaceClassificationTypeIDs:3和8

OUTPUT:所有與RaceClassificationID 3和8中的座圈和任選的任何其它(2,29,12)

這意味着只應該返回92729和92730比賽,因爲這是例子中的所有比賽都返回。

回答

0

我已經設置了兩個表,一個存儲結果集,另一個表示存儲過程的表值參數中的值。見下文。

CREATE TABLE ABC 
(
RCTID INT, 
RID INT 
) 
INSERT INTO ABC VALUES (3,92728) 
INSERT INTO ABC VALUES (3,92729) 
INSERT INTO ABC VALUES (8,92729) 
INSERT INTO ABC VALUES (29,92729) 
INSERT INTO ABC VALUES (12,92729) 
INSERT INTO ABC VALUES (2,92729) 
INSERT INTO ABC VALUES (3,92730) 
INSERT INTO ABC VALUES (8,92730) 
INSERT INTO ABC VALUES (8,92731) 
INSERT INTO ABC VALUES (1,92731) 
GO 
CREATE TABLE TABLEVALUEPARAMETER 
(
VID INT 
) 
INSERT INTO TABLEVALUEPARAMETER VALUES (3) 
INSERT INTO TABLEVALUEPARAMETER VALUES (8) 
GO 
SELECT RID FROM ABC WHERE RCTID IN (SELECT VID FROM TABLEVALUEPARAMETER) GROUP BY 
RID HAVING COUNT(RID) = (SELECT COUNT(VID) FROM TABLEVALUEPARAMETER) 
GO 

如果你在你的機器上運行它,你會注意到它產生了你之後的兩個ID。

因爲您有一個選擇了很多列的存儲過程,所以有必要使用CTE(公用表表達式)。這是因爲如果您想要將當前select語句中的所有列組合在一起,則必須按所有列進行分組,然後重複。

如果第一個CTE提供結果集,然後使用上面選擇的版本,則應該只能生成所需的ID。

如果你不知道CTE的讓我知道!

0

這是一個「設置內集」子查詢的一個例子。解決此問題的一種方法是使用聚合和having子句。這裏是你如何得到RaceId S:

select RaceID 
from RaceClassification rc 
group by RaceID 
having sum(case when RaceClassificationTypeId = 3 then 1 else 0 end) > 0 and 
     sum(case when RaceClassificationTypeId = 8 then 1 else 0 end) > 0; 

having子句中每個條件是數有多少行有各類型。保留每場比賽(因爲> 0)。

您可以使用此作爲一個子查詢得到的所有比賽信息:

select r.* 
from Races r join 
    (select RaceID 
     from RaceClassification rc 
     group by RaceID 
     having sum(case when RaceClassificationTypeId = 3 then 1 else 0 end) > 0 and 
      sum(case when RaceClassificationTypeId = 8 then 1 else 0 end) > 0 
    ) rc 
    on r.RaceID = rc.RaceId; 

你的存儲過程似乎有其他條件。這些也可以添加進來。