从相关表中选择匹配的属性对

时间:2014-01-21 00:51:12

标签: mysql

我有两张桌子,一张是书,另一张是版本。每个版本在“edtype”列中都有“精装”或“平装”等属性。每个图书行可以有多个版本行。

select books.id, books.name, editions.id, editions.edtype from books
join editions on books.id=editions.bookid;

会返回类似的内容:

1  name1  1  hardback
1  name1  2  paperback
2  name2  3  paperback
3  name3  4  hardback

我想要做的是找到有(1)精装版和平装版的书籍:

1  name1

(2)平装书但不是精装版

2  name2

(3)精装本但不是平装版

3  name3

我有以下查询,我认为(1),但我不太相信(因为它返回的行数显得太低):

select id, name
from books
left join  editions e1 on ( books.id = e1.bookid and e1.edtype = 'paperback')
left join  editions e2 on ( books.id = e2.bookid and e2.edtype = 'hardback')
where e1.edtype is not null
and e2.edtype is not null
group by b_id
;

虽然我现在只关注两个属性,但能够将其扩展到版本表中的多个匹配属性会很棒。

感激不尽的任何帮助。

2 个答案:

答案 0 :(得分:0)

让我们从您的查询开始,改进一下以使用表别名并具有不同的列名:

select b.id as book_id, b.name, e.id as edition_id, e.edtype
from books b join
     editions e
     on b.id = e.bookid;

您想要查找图书,以便建议通过图书进行汇总。然后我们需要做一些事情来理解edtype。试试这个:

select b.id as book_id, b.name,
       (case when min(edtype) = max(edtype)
             then min(edtype)
             else 'Both'
        end) as EdTypes
from books b join
     editions e
     on b.id = e.bookid;
group by b.id, b.name;

答案 1 :(得分:0)

按照上面的Gordon代码,我提出了几个子查询,我认为这就是我需要的(至少如果我只比较两个属性):

select * from (
   select books.name, bookid, (case when min(edtype) = max(edtype)
         then min(edtype)
         else 'Both'
    end) as EdTypes
   from
       (select * from editions where (edtype = 'paperback' or edtype = 'hardback'))
     as e2
     join books on e2.bookid = books.id
     group by bookid
    ) as titlelist
 where edtypes = 'Both';

所以,首先选择你感兴趣的行 - 所以你有一个有意义的最小值和最大值。然后处理case语句,加入书籍并消除重复。然后依次选择每种类型以获得计数。