通过查询结果获取ID

时间:2018-02-19 11:11:53

标签: sql sql-server tsql except

我有一个存储过程,其中有两个参数user-defined table type

ALTER PROCEDURE MyProcedure
  @ReceivedBooks tp_Books READONLY,
  @ReceivedIdAuthors tp_Authors READONLY,
AS

用户定义的表类型的结构如下所示:

CREATE TYPE [dbo].[tp_Books] AS TABLE(
    [BookName] [VARCHAR](50) NULL
)

CREATE TYPE [dbo].[tp_Authors] AS TABLE(
    [AuthorIds] [VARCHAR](50) NULL
)

此外,我有两个表BooksAuthors

Books

----------------------------------------------------------------
|      ID      |    Name                    |      Id_Author   |
----------------------------------------------------------------
|       1      |     Hamlet                 |        1         | 
|       2      |     Spartaco               |        2         | 
|      10      |     Romeo and Juliet       |        1         | 
|      11      |     Great Expectations     |        3         | 
|      12      |     Pride and Prejudice    |        5         | 
|      13      |     A Tale of Two cities   |        3         | 
----------------------------------------------------------------

Authors

---------------------------------------------
|      ID      |    Name                    | 
---------------------------------------------
|       1      |     William Shakespeare    | 
|       2      |     Raffaello Giovagnoli   | 
|       3      |     Charles Dickens        | 
|       5      |     Jane Austin            |     
---------------------------------------------

例如,我在存储过程中收到以下值的@ReceivedBooks@idAuthors

 'Hamlet', 'Romeo and Juliet' --@ReceivedBooks
 1, 2, 3, 5                   --@ReceivedIdAuthors

然后我知道1是我想要找到的Id_Author。由于以下EXCEPT语句不返回IdAuthor = 1的任何行(William Shakespeare(ID=1),因此是HamletRomeo and Juliet的作者。而1idAuthor Author我希望找到的原因EXCEPT语句不返回任何行:

SELECT * FROM @ReceivedBooks
EXCEPT 
SELECT Name FROM #Books WHERE IdAuthor IN (1)        

让我举个例子,其中EXCEPT语句返回行。因此,Id_Author不是我想要的。

SELECT * FROM @ReceivedBooks
EXCEPT 
SELECT Name FROM #Books WHERE IdAuthor IN (2) -- 3, 5

所以我的目标是在id_author中找到必要的@ReceivedIdAuthors

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

根据其他澄清评论,您似乎真正需要的是:

  • 查找@ReceivedBooks参数中的所有图书是否属于同一作者,
  • 相应作者是否也出现在@ReceivedIdAuthors参数中。

此处使用的技术称为relational division

select b.Id_Author
from @ReceivedBooks rb
  inner join dbo.Books b on b.Name = rb.BookName
where exists (
  select 0 from @ReceivedIdAuthors ra
  where ra.AuthorId = b.Id_Author
)
group by b.Id_Author
having count(distinct b.Id_Author) = 1;

答案 1 :(得分:1)

基本上,你想要返回@List中不包含此人的第一个元组(人,部门)?

@List有多大?如果相当小,你可以使用:

SELECT dep.Name, 
       pr.ID
FROM dbo.Person AS pr
 INNER JOIN dbo.Department AS dep ON dep.ID = pr.id_Person
WHERE id_Person = @personId
 AND id_Person NOT IN @List
LIMIT 1;

此外,我认为您不需要迭代查询,至少不会给出我在问题描述中看到的数据。