选择中间表中与给定值/值匹配的记录和不在中间表中的记录?

时间:2017-09-30 12:40:54

标签: sql sql-server

我有2张桌子

CREATE TABLE Floor (
Id bigint primary key identity(1,1),
Name
)

表分配用作表格

的中间表
CREATE TABLE Assignment(
Id bigint primary key identity(1,1),
AccountId bigint,
.
.
FloorId bigint, --foreign key for Id column of floor table
.
.
)

如何选择:

  1. 来自楼层表的记录,给出一个XML,其中包含与Assignment表中的accountId匹配的accountId。
  2. 假设:

    DECLARE @accountIdsXML XML = '<AccountId>73</AccountId><AccountId>74</AccountId>'
    
    1. 分配表中没有匹配项的记录
    2. 示例:

      表值:

      Floor Table
      Id    Name
      1     1st Floor
      2     2nd Floor
      3     3rd Floor
      4     4th Floor
      5     5th Floor
      6     6th Floor
      7     7th Floor
      8     8th Floor
      9     9th Floor
      10    10th Floor
      
      Assignment Table
      Id    AccountId   FloorId
      1     73          1
      1     73          2
      1     76          3
      1     79          4
      1     74          5
      1     74          6
      1     79          7
      

      选择输出:

      Floor table
      Id    Name
      1     1st Floor  --matches accountid 73
      2     2nd Floor  --matches accountid 73
      5     5th Floor  --matches accountid 74
      6     6th Floor  --matches accountid 74
      8     8th Floor  --not in assignment table
      9     9th Floor  --not in assignment table
      10    10th Floor --not in assignment table
      

      我基本上想要选择分配给给定的accountid和unchaigned楼层的楼层。

      我设法做了什么

      DECLARE @accountIdsXML XML = '<AccountId>73</AccountId><AccountId>74</AccountId>'
      DECLARE @accountIdsTable as TABLE (Id BIGINT) --table variable to store accountids to be used in the where in operator.
      
      --insert accountids to the table variable
      INSERT INTO @accountIdsTable
      SELECT [aid].[Col].value('(.)[1]', 'BIGINT') FROM @accountIdsXML.nodes('/AccountId') as [aid]([Col])
      
      SELECT F.* FROM [Assignment] A RIGHT JOIN [Floor] F ON A.FloorId = F.Id
      WHERE (A.AccountId IN(SELECT Id from @accountIdsTable) OR F.Id NOT IN (SELECT FloorId FROM Assignment))
      

1 个答案:

答案 0 :(得分:1)

不要从Assignment中选择,而只选择Floor,然后在第一个WHERE子句中加入它们:

SELECT F.* FROM [Floor] F
WHERE EXISTS 
(
    SELECT 1 FROM [Assignment] A 
    INNER JOIN @accountIdsTable AI ON AI.Id = A.AccountId     
    WHERE A.FloorId = F.Id
)
OR F.Id NOT IN (SELECT FloorId FROM Assignment)

这里是link the Fiddle