Я думаю, эта проблема имеет более продвинутую категорию SQL (в этом случае MySQL): у меня есть две таблицы (TABLE_FRUIT
, TABLE_ORIGIN
- только имена примеров), которые имеют столбцы, которые могут быть объединены (fruit_name
).
Рассмотрим следующую диаграмму:
TABLE_FRUIT
fruit_id|fruit_name |variety
--------|----------------------
1|Orange |sweet
2|Orange |large
3|Lemon |wild
4|Apple |red
5|Apple |yellow
6|Pear |early
etc...
TABLE_ORIGIN
fuit_id |fruit_name|Origin
---------|----------|--------
1|Apple | Italy
2|Pear | Portugal
3|Grape | Italy
4|Orange | Spain
5|Orange | Portugal
6|Orange | Italy
etc...
Desired Result:
TABLE_FRUIT_ORIGIN
fuit_id |fruit_name|Origin
---------|----------|--------
1|Orange | Spain
2|Orange | Portugal
3|Apple | Italy
4|Pear | Portugal
Таблицы имеют несколько одинаковых значений в столбцах, которые составляют объединения (fruit_name
). Несмотря на это, мне нужно присоединиться к значениям 1-к-1. Другими словами, значение "Оранжевое" 2 раза в TABLE_FRUIT
и 3 раза в TABLE_ORIGIN
. Я ищу результат двух матчей, один для Испании, один для Португалии. Значение Italy из TABLE_ORIGIN
должно быть проигнорировано, потому что нет третьего значения Orange в TABLE_FRUIT
чтобы соответствовать оранжевому значению в TABLE_ORIGIN
.
Я пробовал все, что мог, но я не могу найти что-то важное в Google. Например, я попытался добавить еще один столбец record_used
и попробовать UPDATE
но безуспешно.
TABLE_ORIGIN
fuit_id |fruit_name|origin |record_used
---------|----------|-----------|-----------
1|Apple | Italy |
2|Pear | Portugal |
3|Grape | Italy |
4|Orange | Spain |
5|Orange | Portugal |
6|Orange | Italy |
etc...
UPDATE
TABLE_FRUIT t1
INNER JOIN
TABLE_ORIGIN t2
ON
(t1.fruit_name = t2.fruit_name)
AND
(t2.record_used IS NULL)
SET
t2.record_used = 1;
Резюме:
TABLE_FRUIT
найдите только одну (следующую первую) запись соответствия в TABLE_ORIGIN
TABLE_ORIGIN
уже была сопоставлена с записью из TABLE_FRUIT
, она не может считаться снова в том же запуске запроса.Вот что я имел в виду с функцией RANK. После комментирования я понял, что у mysql нет встроенной функции RANK над GROUP BY, поэтому пришлось найти эту работу.
SELECT *
FROM (SELECT fruit_name,
@f_rank := IF(@f_name = fruit_name, @f_rank + 1, 1) AS rank,
@f_name := fruit_name
FROM table_fruit
ORDER BY fruit_name DESC) f
INNER JOIN (SELECT fruit_name,
@f_rank := IF(@f_name = fruit_name, @f_rank + 1, 1) AS
rank,
@f_name := fruit_name
FROM table_origin
ORDER BY fruit_name DESC) o
ON f.fruit_name = o.fruit_name
AND f.rank = o.rank;
Объяснение: ранжируйте каждый элемент в таблице для каждого фрукта. Итак, оранжевый в первой таблице будет иметь ранг 1 и 2, а также Apple. Во второй таблице Orange будет иметь ранг 1, 2 и 3, но другие будут иметь только ранг 1. Затем, присоединяясь к таблицам, основанным на именах, вы также можете присоединиться к рангам таким образом, вы получите оранжевый ранг 1 и 2, но оранжевый с рангом 3 не будет соответствовать.
Это основано на моем понимании проблемы. Дайте мне знать, если это требование отличается от того, что я здесь дал.
Существует произвольная связь между количеством записей и порядком этих записей, поэтому используйте методы для соответствия количеству элементов и порядку этих элементов. В MariaDB v10, который поддерживает "функции окна" dense_rank()
и row_number()
это относительно просто:
select row_number() over(order by fn.fruit_id) as fruit_id , fn.fruit_name, o.Origin, fn.variety from ( select fruit_name, variety, fruit_id , dense_rank() over(partition by fruit_name order by fruit_id) rnk from table_fruit ) fn inner join ( select fruit_name, Origin , dense_rank() over(partition by fruit_name order by fruit_id) rnk from table_origin ) o on fn.fruit_name = o.fruit_name and fn.rnk = o.rnk
fruit_id | fruit_name | Origin | variety -------: | :--------- | :------- | :------ 1 | Orange | Spain | sweet 2 | Orange | Portugal | large 3 | Apple | Italy | red 4 | Pear | Portugal | early
dbfiddle здесь
Чистое решение MySQL немного сложнее, потому что оно требует использования @variables, который заменит эти функции окна.