Ошибка при выполнении запроса с объединением таблиц не отображается - PullRequest
0 голосов
/ 20 февраля 2019

Есть запрос, который пользователь имеет в закладках этого продукта, также учитывает понравившиеся продукты и отображает все продукты в таблице:

SELECT P.*, 
  COUNT(L.USER_ID) AS LIKES, 
  (B.PRODUCT_ID = P.PRODUCT_ID AND B.USER_ID = B.USER_ID) AS BOOKMARKS 
    FROM PRODUCTS AS P 
      LEFT JOIN LIKES_PRODUCTS AS L ON (L.PRODUCT_ID = P.PRODUCT_ID) 
      LEFT JOIN BOOKMARKS_PRODUCTS AS B ON (B.PRODUCT_ID = P.PRODUCT_ID)
        GROUP BY P.PRODUCT_ID, B.PRODUCT_ID, B.USER_ID ORDER BY P.PRODUCT_ID

Но он добавляет продукт к существующим впродукт и не отображает false, но только true, а ложное отображает null для его места:

product_id |  product_name | ... | LIKES | BOOKMARKS |
------------------------------------------------------
     1     |     name 1    | ... |   0   |   true    |
     1     |     name 1    | ... |   0   |   true    |
     2     |     name 2    | ... |   0   |   NULL    |
     3     |     name 3    | ... |   0   |   NULL    |
     4     |     name 4    | ... |   0   |   NULL    |

Почему он добавляет мне дополнительный продукт 1 и не отображает столбец закладкиfalse, но разве это null?Где я не прав, помогите мне, пожалуйста.

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

Зная, что поле B.PRODUCT_ID будет либо равным значению P.PRODUCT_ID, или NULL, вы можете использовать IS NULL иIS NOT NULL операторы сравнения задают этот вопрос вместо этого.

SELECT […] (B.PRODUCT_ID IS NOT NULL) AS PRODUCT_IS_IN_BOOKMARKS […]

Вы имеете дело с ужасом NULL и трехзначной логики .NULL все усложняет!

не отображает ложный столбец закладки, но имеет значение null?

Краткое объяснение: NULL не является значением;это заполнитель, не имеющий значения.На вопрос «это значение равно not-have-a-value?» Нет никакого значимого ответа, поэтому SQL диктует, что ответ равен NULL.

Более подробное объяснение: ваши объединения LEFT JOIN, так что вызапрашивать строки , даже если справа от этого соединения ничего нет.Когда в таблице BOOKMARKS нет соответствующего кортежа, его столбцы в наборе результатов имеют значение NULL.Таким образом, ваше вычисленное поле (B.PRODUCT_ID = P.PRODUCT_ID AND B.USER_ID = B.USER_ID) будет, при отсутствии соответствующей записи BOOKMARKS, сравниваться на равенство с NULL;и так получим результат NULL.

0 голосов
/ 20 февраля 2019

вы можете использовать coalesce() для замены нуля на другой неизвестный идентификатор, который может никогда не существовать в вашем идентификаторе, и вернуть false, потому что проверка null = null невозможна

SELECT P.*, 
  COUNT(L.USER_ID) AS LIKES, 
  (coalesce(B.PRODUCT_ID,-99999) = P.PRODUCT_ID AND ) AS BOOKMARKS 
    FROM PRODUCTS AS P 
      LEFT JOIN LIKES_PRODUCTS AS L ON (L.PRODUCT_ID = P.PRODUCT_ID) 
      LEFT JOIN BOOKMARKS_PRODUCTS AS B ON (B.PRODUCT_ID = P.PRODUCT_ID)
        GROUP BY P.PRODUCT_ID, B.PRODUCT_ID, B.USER_ID ORDER BY P.PRODUCT_ID
0 голосов
/ 20 февраля 2019

Кажется, что некоторые из B.PRODUCT_ID, P.PRODUCT_ID, B.USER_ID и B.USER_ID имеют значение SQL NULL, поэтому результат равен NULL.

«NULL» означает «неизвестно» в SQL.

Если вы проверяете две вещи на равенство, и одна из них неизвестна, результат неизвестен.

Если два условия должны быть истинными, но результат одного условия неизвестен,общий результат неизвестен.

Короче говоря, NULL является «заразным».

Может быть, это то, что вы хотите:

    B.PRODUCT_ID IS NOT DISTINCT FROM P.PRODUCT_ID
AND B.USER_ID    IS NOT DISTINCT FROM B.USER_ID

IS NOT DISTINCT FROM похоже на =, но обрабатывает NULL как нормальное значение.

...