簡體   English   中英

同一張表的兩個不同列的MySql Distinct值

[英]MySql Distinct values of two different columns of the same table

我有2個表,Products和Genre。在products表中,它關於產品的所有信息包括兩種流派(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一致的計數並列出不同的計數

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則此方法將不起作用

5     product5            1            1

鑒於您具有要連接的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演示

如果沒有,您仍然可以使用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演示


編輯: UNION方法不會( 也不能 )返回任何計數為0的行。“ obvious”方法會返回,因為我使用了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演示 )這實際上是用於過濾掉此類行的通用方法。

我沒有針對JW的解決方案進行基准測試,以查看哪種效率更高,因為這將需要一些實際數據。 如果您的數據集很小,那么這兩種方法都可能無關緊要。

(結果將在很大程度上取決於MySQL對其的優化程度:如果天真執行JW的嵌套LEFT JOIN在大型數據集上可能會變得非常慢,但是我不確定MySQL是否足夠聰明而不這樣做。依賴子查詢可能不會得到很多優化,但是即使有必要的索引,即使是幼稚的執行也應該相當快。)


編輯3:請注意,通常,此問題是由錯誤的表設計引起的。 最好更改架構以使用聯結表如此答案中所述

這樣一來,您可以讓每種產品屬於任意數量的流派,並可以使用以下簡單查詢輕松地計算每種流派中的產品:

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

用genre_id2編寫類似的語句,並與原始結果進行並集

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM