How can I exclude LEFT JOINed tables from TOP in S

2019-07-07 10:13发布

Let's say I have two tables of books and two tables of their corresponding editions.

I have a query as follows:

SELECT TOP 10 * FROM
(SELECT hbID, hbTitle, hbPublisherID, hbPublishDate, hbedID, hbedDate
 FROM hardback
 LEFT JOIN hardbackEdition on hbID = hbedID
 UNION 
 SELECT pbID, pbTitle, pbPublisher, pbPublishDate, pbedID, pbedDate
 FROM paperback
 Left JOIN paperbackEdition on pbID = pbedID
) books
WHERE hbPublisherID = 7
ORDER BY hbPublishDate DESC

If there are 5 editions of the first two hardback and/or paperback books, this query only returns two books. However, I want the TOP 10 to apply only to the number of actual book records returned. Is there a way I can select 10 actual books, and still get all of their associated edition records?

In case it's relevant, I do not have database permissions to CREATE and DROP temporary tables.

Thanks for reading!

Update

To clarify: The paperback table has an associated table of paperback editions. The hardback table has an associated table of hardback editions. The hardback and paperback tables are not related to each other except to the user who will (hopefully!) see them displayed together.

3条回答
姐就是有狂的资本
2楼-- · 2019-07-07 10:27

If I understand you correctly, you could get the 10 books with all associated editions by

  • Using a WITH statement to return the initial, complete resultset
  • select 10 distinct books by using a GROUP BY
  • JOIN the results of this group to retain all information from given 10 books.

SQL Statement

;WITH books AS (
  SELECT  hbID, hbTitle, hbPublisherID, hbPublishDate, hbedID, hbedDate
  FROM    hardback
          LEFT JOIN hardbackEdition on hbID = hbedID
  WHERE   hbPublisherID = 7          
  UNION ALL
  SELECT  pbID, pbTitle, pbPublisher, pbPublishDate, pbedID, pbedDate
  FROM    paperback
          LEFT JOIN paperbackEdition on pbID = pbedID
  WHERE   hbPublisherID = 7
)
SELECT  *
FROM    books b
        INNER JOIN (
          SELECT TOP 10 hbID
          FROM   books
          GROUP BY
                hbID
        ) bt ON bt.hbID = b.hbID

or if you prefer to write the where clause only once

;WITH books AS (
  SELECT  hbID, hbTitle, hbPublisherID, hbPublishDate, hbedID, hbedDate
  FROM    hardback
          LEFT JOIN hardbackEdition on hbID = hbedID
  UNION ALL
  SELECT  pbID, pbTitle, pbPublisher, pbPublishDate, pbedID, pbedDate
  FROM    paperback
          LEFT JOIN paperbackEdition on pbID = pbedID
)
, q AS (
  SELECT  *
  FROM    books
  WHERE   hbPublisherID = 7          
)
SELECT  *
FROM    q b
        INNER JOIN (
          SELECT TOP 10 hbID
          FROM   q
          GROUP BY
                hbID
        ) bt ON bt.hbID = b.hbID
查看更多
啃猪蹄的小仙女
3楼-- · 2019-07-07 10:28

This should grab the ten most recently published titles with a hardback from publisher 7:

select  *
from    (
        select  top 10 title
        from    hardback
        where   hbPublisherID = 7
        group by
                title
        order by
                hbPublishDate desc
        ) top_titles
left join
      hardback
on    hardback.hbTitle = top_titles.title
left join
      paperback
on    paperback.pbTitle = top_titles.title
查看更多
Lonely孤独者°
4楼-- · 2019-07-07 10:44

Not so easy. You need to apply Top 10 to only the hardback and paperback tables, without the join. Then join the result to the data.

The following query only works when the hbID and pbID are always unique. If not, it gets more complicated. You need to separate them or add another column to the query to distinguish them.

SELECT *
FROM
  (SELECT hbID as id, hbTitle, hbPublisherID, hbPublishDate, hbedID, hbedDate
   FROM hardback
   LEFT JOIN hardbackEdition on hbID = hbedID
   UNION 
   SELECT pbID as id, pbTitle, pbPublisher, pbPublishDate, pbedID, pbedDate
   FROM paperback
   Left JOIN paperbackEdition on pbID = pbedID
  ) books
INNER JOIN 
  (SELECT TOP 10 * 
  FROM
    (SELECT hbID as id, hbPublisherID as publishedId, hbPublishDate as publishDate
     FROM hardback
     UNION 
     SELECT pbID as id, pbPublisherID as publishedId, pbPublishDate as publishDate
     FROM paperback
    ) 
  WHERE publisherID = 7
  ORDER BY publishDate DESC
  ) topTen 
  on books.id = TopTen.id
查看更多
登录 后发表回答