Как использовать COUNT, чтобы получить нулевые значения с MySQL? - PullRequest
1 голос
/ 02 июля 2011

Я прочитал несколько вопросов об этой проблеме в stackoverflow: Похоже, что COUNT следует использовать с правильным соединением, чтобы отобразить суммы всех элементов, включая те, которые суммируют ноль.

Я не могу сделать это с моим делом, после нескольких часов головной боли ...

Ну, у меня есть 2 таблицы. Первый называется "words2" со списком слов. Второй называется "links2". Он связывает воедино два слова: idWord1 и idWord2. (Нет ссылок, связывающих два одинаковых слова)

Для каждого слова я хотел бы знать, сколько ссылок используется, даже если ссылки нет.

Это мой запрос:

SELECT *, COUNT(*) AS qty  
FROM ( 
    SELECT *
    FROM words2
    LEFT OUTER JOIN links2 AS linksA ON words2.idWord = linksA.idWord1 

    UNION

    SELECT *
    FROM words2
    LEFT OUTER JOIN links2 AS linksB ON words2.idWord = linksB.idWord2
) AS tmp
WHERE idUser = 3 AND linkType = 'individual'
GROUP BY word ORDER BY word

Работает нормально, если у меня нет результатов для неиспользованных слов, которые не отображаются.

Большое спасибо за вашу помощь!

Ответы [ 2 ]

3 голосов
/ 02 июля 2011

Чтобы сделать это с вашим исходным запросом, измените счетчик вызовов на COUNT(idWord1).Это заставит его считать количество раз, когда idWord1 НЕ равен NULL.Прямо сейчас он считает количество периодов строк, поэтому вы получите 1, где вы должны получить ноль.

Вот мой примерный набор данных:

words2
-------
idWord
-------
foo
bar
baz
biz
buzz

links2
-------
idWord1 | idWord2
-------
foo     | bar
foo     | baz
bar     | baz
buzz    | foo
buzz    | bar

(Этот набор данных не учитывает idUserи linkType полей, потому что ваш исходный вопрос не описывает, как они используются, и они не имеют отношения к ответу.)

Когда я запускаю ваш запрос на моем наборе данных, я получаю это:

idWord | idWord1 | idWord2 | linkCount
--------------------------------------
bar    | bar     | baz     | 3
baz    | NULL    | NULL    | 2
biz    | NULL    | NULL    | 1
buzz   | buzz    | foo     | 2
foo    | foo     | bar     | 3

Также обратите внимание, что COUNT(*) будет дороже в зависимости от используемого вами механизма хранения. Подробнее см. Этот вопрос.

Когда я изменяю счетчик на COUNT(idWord1), я получаю это:

idWord | idWord1 | idWord2 | linkCount
--------------------------------------
bar    | bar     | baz     | 3
baz    | NULL    | NULL    | 2
biz    | NULL    | NULL    | 0
buzz   | buzz    | foo     | 2
foo    | foo     | bar     | 3

Вот еще более простой запрос, который не использует подзапроси соединяет слова2 со ссылками2, используя оператор OR:

SELECT
  words2.idWord
  -- this will count the number of links to each word
  -- if there are no links the COUNT() call will return 0
  , COUNT(idWord1) AS linkCount
FROM words2
  LEFT JOIN links2
    ON words2.idWord = links2.idWord1
      OR words2.idWord = links2.idWord2
GROUP BY words2.idWord
ORDER by words2.idWord

При запуске в наборе образцов данных я получаю следующие результаты:

idWord | linkCount
-------------------
bar    | 3
baz    | 2
biz    | 0
buzz   | 2
foo    | 3
0 голосов
/ 02 июля 2011
SELECT
    w.idWord
  , ( SELECT COUNT(*) 
      FROM links2 AS l
      WHERE l.idWord1 = w.idWord
    ) +
    ( SELECT COUNT(*) 
      FROM links2 AS l
      WHERE l.idWord2 = w.idWord
    ) AS linkCount
FROM words2 AS w

или

SELECT
    w.idWord
  , ( SELECT COUNT(*) 
      FROM links2 AS l
      WHERE l.idWord1 = w.idWord
         OR l.idWord2 = w.idWord
    ) AS linkCount
FROM words2 AS w
...