簡體   English   中英

SQL多對多關系

[英]SQL Many to Many relationship

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

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子句)。 我希望存儲過程僅返回具有在表值參數中提供的所有分類的種族。

例:

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

RaceClassificationTypeTable參數中的RaceClassificationTypeIDs:3和8

輸出:所有具有RaceClassificationID 3和8的種族,以及其他任意種族(2、29、12)

這意味着僅應返回種族92729和92730,因為示例中的所有種族均已返回。

這是“集內集”子查詢的示例。 解決此問題的一種方法是使用聚合和having子句。 這是如何獲取RaceId的:

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;

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

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

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,請告訴我!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM