почему INNER JOIN возвращает пустой набор для двух таблиц, содержащих совпадающие данные? - PullRequest
0 голосов
/ 15 января 2019

MySQL возвращает пустой набор, когда я присоединяюсь к общему значению UPC. Я могу сделать левое соединение и увидеть то же значение UPC на правой стороне, когда я делаю правое соединение. Почему внутреннее соединение возвращает пустой набор ???? Как заставить объединение работать ??

MySQL>

select
    upc_descriptions.UPC,
    left(upc_descriptions.Description,15) as Description,
    product_upc.ProductCode, product_upc.UPC
from upc_descriptions
left join product_upc
    ON upc_descriptions.UPC=product_upc.UPC
where upc_descriptions.UPC = 009326204994;

| UPC          | Description     | ProductCode | UPC  |
+--------------+-----------------+-------------+------+
| 009326204994 | KWIKSET PRO ADJ | NULL        | NULL |
| 009326204994 | KWIKSET PRO ADJ | NULL        | NULL |
+--------------+-----------------+-------------+------+
2 rows in set (0.04 sec)

MySQL>

select
    upc_descriptions.UPC,
    upc_descriptions.Description,
    product_upc.ProductCode,
    product_upc.UPC
from upc_descriptions
right join product_upc
    ON upc_descriptions.UPC=product_upc.UPC
where product_upc.UPC = 009326204994;


+------+-------------+-------------+-----------------+
| UPC  | Description | ProductCode | UPC             |
+------+-------------+-------------+-----------------+
|NULL | NULL        | 239070      | 009326204994
|NULL | NULL        | 239070      | 00009326204994
+------+-------------+-------------+-----------------+
2 rows in set, 2 warnings (0.03 sec)

MySQL>

select
    upc_descriptions.UPC,
    upc_descriptions.Description,
    product_upc.ProductCode,
    product_upc.UPC
from upc_descriptions
inner join product_upc
    ON upc_descriptions.UPC = product_upc.UPC
where product_upc.UPC = 009326204994;
Empty set (0.03 sec)

Таблица определений:

mysql> describe upc_descriptions;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| UPC         | varchar(20)  | NO   |     | NULL    |                |
| Description | varchar(256) | NO   |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> describe product_upc;
+-------------+-------------+------+-----+---------+----------------+
| Field       | Type        | Null | Key | Default | Extra          |
+-------------+-------------+------+-----+---------+----------------+
| id          | int(11)     | NO   | PRI | NULL    | auto_increment |
| ProductCode | varchar(50) | NO   |     | NULL    |                |
| UPC         | varchar(20) | NO   |     | NULL    |                |
+-------------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

Вот значения, которые были загружены в таблицу.

cat productCode-UPC_sorted.csv | grep 009326204994
239070,009326204994
239070,00009326204994

kid927 предложил приводить в качестве SIGNED при определении таблиц индекса для объединения. Сначала я думал, что это сработает очень хорошо, но потом, копаясь глубже, я столкнулся с другой странной проблемой. Вот запрос и результат:

mysql>

select 
    upc_descriptions.UPC,left(upc_descriptions.Description,15) as Description, 
    product_upc.ProductCode, product_upc.UPC 
from upc_descriptions left join product_upc 
    ON CAST(upc_descriptions.UPC as SIGNED)=CAST(product_upc.UPC as SIGNED)
where upc_descriptions.UPC = 009326204994;

| UPC          | Description     | ProductCode | UPC             |
+--------------+-----------------+-------------+-----------------+
|9326204994    | KWIKSET PRO ADJ | 239070      | 009326204994
|9326204994    | KWIKSET PRO ADJ | 239070      | 009326204994
|009326204994  | KWIKSET PRO ADJ | 239070      | 00009326204994
|009326204994  | KWIKSET PRO ADJ | 239070      | 00009326204994
+--------------+-----------------+-------------+-----------------+
4 rows in set, 65535 warnings (0.07 sec)

Когда все становится действительно странным, я убираю предложение WHERE и просто смотрю на объединяемые данные. Я получаю странные результаты, когда mysql сопоставляет одну строку с подстрокой другой таблицы, что приводит к неверному результату. Это имеет смысл, только если выполняется сравнение строк типа CHAR, но когда я явно приводил данные UPC как SIGNED int, он должен сравнивать числа, а не сравнивать подстроки ... так что я действительно запутался в том, что здесь происходит Вот пример:

mysql>

SELECT 
    upc_descriptions.UPC,
    left(upc_descriptions.Description,15) as Description,
    product_upc.ProductCode, 
    product_upc.UPC 
FRP, upc_descriptions INNER JOIN product_upc 
    ON CAST(upc_descriptions.UPC as SIGNED)=CAST(product_upc.UPC as SIGNED);

| UPC          | Description     | ProductCode | UPC             |
+--------------+-----------------+-------------+-----------------+
| 4036280125   | PASS PRO SERIES | 21096285    | 694036280125
| 4036960027   | KWIKSET PRO SIN | 21099030    | 694036960027
+--------------+-----------------+-------------+-----------------+
913 rows in set, 65535 warnings (21.33 sec)

Посмотрите, как UPC в левой таблице (4036280125) возвращает совпадение с правой таблицей, где он является подстрокой в ​​номере (694036280125). Это похоже на совпадение строки / символа, несмотря на то, что я использовал его как SIGNED. Кроме того, это неправильно, поскольку число в правой таблице (694036280125) относится к совершенно другому продукту.

Ответы [ 3 ]

0 голосов
/ 15 января 2019

Причина, по которой вы не получаете результатов, заключается в том, что столбцы, к которым вы присоединяетесь, являются строками. Когда вы сравниваете их с целым числом, MySQL выполняет преобразование типа строки в целое число, и в этом случае значения равны. Однако, когда они сравниваются как строки, они не являются. Попробуйте это:

SELECT '01' = 1, '1' = 01, '01' = '1'

Выход:

'01' = 1    '1' = 01    '01' = '1'
1           1           0

Есть способы обойти это. Вы можете преобразовать свои значения в числа или обрезать начальные нули по значениям:

SELECT CAST('01' AS UNSIGNED) = CAST('1' AS UNSIGNED)
SELECT TRIM(LEADING '0' FROM '01') = TRIM(LEADING '0' FROM '1')

Демонстрация по dbfiddle

Вот демоверсия на dbfiddle вашего запроса, работающая нормально с использованием TRIM.

0 голосов
/ 15 января 2019

Ник побил меня, но я попробовал с CAST(UPC as SIGNED) и CAST(UPC as UNSIGNED), и это сработало:

select upc_descriptions.UPC,left(upc_descriptions.Description,15) as Description, product_upc.ProductCode, product_upc.UPC from upc_descriptions left join product_upc ON CAST(upc_descriptions.UPC as SIGNED)=CAST(product_upc.UPC as SIGNED) where upc_descriptions.UPC = 009326204994;

Я ссылаюсь ПОДПИСАННОЕ и ПОДПИСАННОЕ объяснение в этом посте.

0 голосов
/ 15 января 2019

Вы можете попробовать ниже - вы можете видеть, что ваши коды UPC не совпадают в двух таблицах - одна таблица имеет перед номером 00 перед кодом, и поэтому она не отображается для внутреннего соединения

    select upc_descriptions.UPC, upc_descriptions.Description, product_upc.ProductCode, product_upc.UPC 
    from upc_descriptions inner join product_upc 
    ON upc_descriptions.UPC=concat('00',product_upc.UPC)
    where product_upc.UPC='009326204994';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...