MySql同一个表的两个不同列的不同值

时间:2013-04-25 00:11:10

标签: mysql

我有2张桌子,产品和类型.. 在产品表中,产品的所有信息包括两种类型,(genre_id和genre_id2),只需要第一种,所以第二种可能有空值

在类型表中的

我有所有可能的类型名称,其ID与产品表的类型ID相关

TABLE PRODUCTS
--------------
id    product_name    genre_id      genre_id2
-------------------------------------------------
1     product             1             2
2     product2            2 
3     product3            1             4
4     product4            3             4

TABLE GENRE
-----------
id    genre_name
-------------------------------------------------
1     genre1
2     genre2
3     genre3
4     genre4

我想选择所有不同类型,看看我有多少类型的产品

类似这样的事情

RESULT
------
genre_id       count
-----------------------
    1            2
    2            2
    3            1
    4            2

我有这个陈述

SELECT DISTINCT p.genre_id AS genre, g.genre_name,  COUNT(p.genre_id) AS cnt
FROM products AS p
JOIN genre AS g
ON p.genre_id=g.id
GROUP BY genre_id
ORDER BY cnt DESC

但仅适用于genre_id,我不知道如何在此声明中加入genre_id2并添加与genre_id重合的计数并列出不同的计数

3 个答案:

答案 0 :(得分:3)

SELECT  a.ID, COUNT(DISTINCT b.ID) + COUNT(DISTINCT c.ID)
FROM    Genre a
        LEFT JOIN products b
            ON a.ID = b.genre_id
        LEFT JOIN products c
            ON a.ID = c.genre_id2
GROUP BY a.ID

警告:如果您的记录具有相同的genre_id and genre_ID2 ex

,则此功能无效
5     product5            1            1

答案 1 :(得分:2)

鉴于您要加入genre表,“显而易见”的解决方案将是:

SELECT genre.id AS genre, COUNT(products.id) AS n
FROM genre
  LEFT JOIN products ON genre.id IN (genre_id, genre_id2)
GROUP BY genre.id

SQLFiddle demo

如果你没有,你仍然可以使用UNION

来做到这一点
SELECT genre, COUNT(*) as n
FROM
  (SELECT id, genre_id AS genre FROM products
   WHERE genre_id IS NOT NULL
   UNION
   SELECT id, genre_id2 AS genre FROM products
   WHERE genre_id2 IS NOT NULL) AS foo
GROUP BY genre

SQLFiddle demo


编辑 UNION方法不会(并且不能)返回计数为0的任何行。“明显的”方法会,因为我使用了LEFT JOIN。如果您想要它们,您可以通过仅用LEFT JOIN替换JOIN来消除它们的“显而易见”方法。


编辑2:使用适当的索引(genre_idgenre_id2各一个),并根据实际数据集的大小和内容,以下解决方案使用依赖子查询可能比上述任何一个更有效:

SELECT genre.id AS genre,
  (SELECT COUNT(*) FROM products WHERE genre.id = genre_id) +
  (SELECT COUNT(*) FROM products WHERE genre.id = genre_id2) AS n
FROM genre

要消除零计数的行,只需坚持

HAVING n > 0

在查询结束时。 (SQLFiddle demo)这实际上是过滤掉这些行的通用方法。

我没有针对JW's solution对此进行基准测试,以确定哪一个更有效,因为这需要一些实际数据。如果您的数据集相当小,则无论哪种方式都无关紧要。

(结果将在很大程度上取决于MySQL如何优化它们:如果天真地执行,JW的嵌套LEFT JOIN在大型数据集上会变得非常慢,但我不确定MySQL是否足够智能不会同时,我的依赖子查询可能不会得到很多优化,但只要有必要的索引,即使是天真的执行也应该相当快。)


编辑3:请注意,一般来说,这个问题源于糟糕的表格设计。最好更改架构以使用junction table,如图所示。在this answer

这将允许您让每个产品属于任意数量的类型,并允许您使用如下简单查询轻松统计每个类型的产品:

SELECT genre.id AS genre, COUNT(products.id) AS n
FROM genre
  JOIN product_genre ON genre.id   = product_genre.genre
  JOIN products      ON product.id = product_genre.product
GROUP BY genre.id

答案 2 :(得分:1)

用genre_id2写一个类似的语句并与原始结果进行联合