0

2 つのビューから残りの行を選択する必要がある SQL Server データベースがあります。

その背後にある考え方は次のとおりです。ゲームの部門を 1 つのテーブルに保存し、氏族を別のテーブルに保存します。

  • vwGetGameDivisions、分割できるすべてのゲームを取得します。
  • vwGetClanDivisionsは、クランがサブスクライブしている現在のすべてのゲーム ディビジョンを取得します。

現在、

SELECT dbo.vwGetGameDivisions.name, dbo.vwGetClanDivisions.clanName
FROM   dbo.vwGetClanDivisions 
RIGHT OUTER JOIN
       dbo.vwGetGameDivisions
    ON dbo.vwGetClanDivisions.gameName = dbo.vwGetGameDivisions.name

登録されているすべての「ディビジョン」と「クラン」を取得します。

残りの部門 (特定のクランが登録されていない残りの部門)を表示したいので、それを にバインドしてdropDownList、クランがまだサブスクライブできるものを確認できるようにします。

私はまだSQLクエリの初心者であり、これについてどうすればよいかさえ知りません..

を試しましWHERE (dbo.vwGetClanDivisions.clanName = NULL)たが、それはクランをまったく持たない師団のみを返します。

編集 - 構造:

CREATE TABLE [dbo].[tblSiteClanGameDivision](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [clanId] [int] NOT NULL,
    [gameId] [int] NOT NULL,
    [removed] [tinyint] NOT NULL,
    [dateAdded] [datetime] NOT NULL,
 CONSTRAINT [PK_tblSiteClanGameDivision] PRIMARY KEY CLUSTERED 

CREATE TABLE [dbo].[tblSiteGame](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](200) NOT NULL,
    [description] [nvarchar](700) NULL,
    [thumbnailLocation] [nvarchar](100) NULL,
    [genreId] [int] NOT NULL,
    [isDivision] [tinyint] NOT NULL,
 CONSTRAINT [PK__tblGame__3213E83F03317E3D] PRIMARY KEY CLUSTERED 

CREATE VIEW [dbo].[vwGetClanDivisions]
AS
SELECT dbo.tblSiteClanDetail.clanId, dbo.tblSiteClanDetail.clanName, dbo.tblSiteGame.id AS gameId, dbo.tblSiteGame.name AS gameName, 
                         dbo.tblSiteClanGameDivision.removed, dbo.tblSiteClanGameDivision.dateAdded
FROM   dbo.tblSiteClanDetail 
INNER JOIN  dbo.tblSiteClanGameDivision ON dbo.tblSiteClanDetail.id = dbo.tblSiteClanGameDivision.clanId 
INNER JOIN dbo.tblSiteGame ON dbo.tblSiteClanGameDivision.gameId = dbo.tblSiteGame.id

GO

CREATE VIEW [dbo].[vwGetGameDivisions]
AS
SELECT  id, name, thumbnailLocation, isDivision
FROM    dbo.tblSiteGame
WHERE   (isDivision = 1)

GO
4

2 に答える 2

2

鍵はINNER JOIN、クランがサインアップしているディビジョンをフェッチするために使用し、そうでLEFT JOINないディビジョンをフェッチするために使用することです。 LEFT JOINクランが登録していない場合でも師団を返します。次に、次のように、所属する師団を除外します。

-- Get matching divisions
SELECT gd.ID, gd.name, cd.clanName
FROM dbo.vwGetClanDivisions cd
INNER JOIN dbo.vwGetGameDivisions gd ON cd.gameId = gd.id

-- Get remaining divisions
SELECT gd.ID, gd.name, cd.clanName
FROM dbo.vwGetClanDivisions cd
LEFT JOIN dbo.vwGetGameDivisions gd ON cd.gameId = gd.id
WHERE gd.gameName IS NULL

2 番目のクエリは aを使用しLEFT JOINて結合の両側のすべての行を取得することに注意してください。WHERE句は、そのクランに一致するゲーム部門がない行のみを表示します。テーブル名のエイリアス (上記のように) を使用して、クエリを短縮することもできます。

編集: を使用する必要がありRIGHT OUTER JOINましたが、テストでも機能しませんでした。ただし、@Vincent James によって提供された使用方法は有効ですNOT IN(検索対象のクランを指定する必要があることに注意してください。そうしないと、空の部門のリストのみが取得されます)。非常に基本的な SQL の例を次に示します。

CREATE TABLE #A (ID int, bID int)
CREATE TABLE #B (ID int)

INSERT INTO #B (ID) SELECT 1
INSERT INTO #B (ID) SELECT 2
INSERT INTO #B (ID) SELECT 3
INSERT INTO #B (ID) SELECT 4
INSERT INTO #B (ID) SELECT 5

INSERT INTO #A (ID, bID) SELECT 1,1
INSERT INTO #A (ID, bID) SELECT 1,2
INSERT INTO #A (ID, bID) SELECT 1,3
INSERT INTO #A (ID, bID) SELECT 2,1
INSERT INTO #A (ID, bID) SELECT 2,2
INSERT INTO #A (ID, bID) SELECT 3,3
INSERT INTO #A (ID, bID) SELECT 3,4

SELECT DISTINCT #B.ID 
FROM #B 
WHERE ID NOT IN(SELECT bID FROM #A WHERE ID = 1)

DROP TABLE #A
DROP TABLE #B

これにより、ID が 1 の #A のエントリは、ID が 1、2、または 3 (4 または 5 ではない) の #B にリンクされます。上記のクエリを実行すると、NOT INメソッドが正しい 4 と 5 を返すことがわかります。RIGHT OUTER JOINこれの目的は、#A で見つかったかどうかに関係なく、#B からすべての行を返すことであるため、なぜ機能しないのか完全にはわかりません。

編集 2:WHERE行が返されないようにする 2 つの競合する句があったため、Right Outer 結合メソッドを削除しました。左側のIDで選択する必要があるため、指定されたテーブル構造で外部結合を使用することはできませんが、左側がnullの場合のみです。 NOT IN上記のように、正しい方法です。

編集 3 作成する必要があるストアド プロシージャは次のとおりです。これは、 SQL インジェクション攻撃から保護されるため、クエリをハード コーディングするよりも優れています。

CREATE PROCEDURE [dbo].[GetEmptyClanDivisions]
(
    @ClanID INT
)
AS
BEGIN
    -- Get the clan name
    DECLARE @ClanName nvarchar(255)
    SET @ClanName = SELECT TOP 1 clanName FROM tblSiteClanDetail WHERE clanId = @ClanID 

    -- Get a list of divisions the clan is registered for
    SELECT DISTINCT ID, name, @ClanName 
    FROM vwGetGameDivisions
    WHERE ID NOT IN(
        SELECT gameId 
        FROM tblSiteClanGameDivision 
        WHERE clanId = @ClanID
    )
END
于 2013-05-10T10:14:09.060 に答える