Search code examples
sqlsql-servert-sqlexcept

Get ID by query result


I have a stored procedure which has two parameters of user-defined table type:

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

The structure of user-defined table type looks like this:

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

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

In addition, I have two tables Books and Authors:

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            |     
---------------------------------------------

For example, I receive @ReceivedBooks and @idAuthors with following values at my stored procedure:

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

then I can know that 1 is the Id_Author which I want to find. As the following EXCEPT statement returns no rows for IdAuthor = 1(William Shakespeare(ID=1) is an author of Hamlet and Romeo and Juliet). And 1 is the idAuthor of Author that I want to found cause EXCEPT statement returns no rows:

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

Let me show an example, where EXCEPT statement returns rows. Consequently, this Id_Author is not what I want.

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

So my goal is to find necessary id_author in @ReceivedIdAuthors.

How can I achieve this?


Solution

  • Based on additional clarification comments, it seems all you really need is:

    • To find whether all the books in your @ReceivedBooks parameter belong to the same author, and
    • Whether a corresponding author is also present in the @ReceivedIdAuthors parameter.

    The technique to use here is called 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;