Как объединить несколько двоичных таблиц на основе списка идентификаторов, полученных из одной из них - PullRequest
1 голос
/ 18 ноября 2011

У меня есть несколько двоичных таблиц, которые, вместе взятые, моделируют данные словаря. Каждая таблица состоит из двух столбцов: «id» для идентификатора записи и «data» для описания свойства записи. Для каждой записи может быть несколько одинаковых свойств, поэтому запись с идентификатором «1» может содержать два написания, пять примеров фраз и т. Д., Все они привязаны к идентификатору записи. Как некоторые случайные данные примера:

table1:

id    data
1     "a"
1     "b"
1     "c"
2     "a"
2     "x"
...

table2:

id    data
1     "a"
2     "b"
...

Таблица3:

id    data
1     "a"
1     "b"
2     "a"
2     "b"
2     "c"
2     "d"
...

Я хотел бы запросить эти данные, чтобы на основе поиска в таблице ... для записей со значением "a" я получил полный набор табличных значений. Скажем, например, что я хочу получить данные для всех записей со свойством table1 "a", которое даст список идентификаторов {1,2}. Я бы хотел получить результаты

результат:

id    t1prop    trprop    t3prop
1     a, b, c   a         a, b
2     a, x      b         a, b, c, d

Получение всех соответствующих идентификаторов из одной таблицы тривиально,

SELECT DISTINCT id FROM table1 WHERE data LIKE "a"

Но как мне использовать этот результат в большем выборе? Если я попытаюсь соединить это с таблицей2 на «id», я не могу свернуть table2.data в одну строку, как вы можете сделать с помощью GROUP_CONCAT, так как я могу убедиться, что есть только один результат для каждого отдельного идентификатора с несколькими записями за таблицу, свернутую в (в данном случае запятую) разделенные списки?

Я пытался посмотреть, смогу ли я просто объединить две или более таблиц, что работает для двух:

SELECT
  t1.id AS id,
  GROUP_CONCAT(DISTINCT t2.data SEPARATOR ', ') AS t2properties,
FROM
  (SELECT DISTINCT id FROM table1 WHERE data LIKE "a") AS t1
  JOIN table2 AS t2 ON t1.id=t2.id
GROUP BY t2.data

, но не работает более двух:

SELECT
  t1.id AS id,
  GROUP_CONCAT(DISTINCT t2.data SEPARATOR ', ') AS t2properties,
  GROUP_CONCAT(DISTINCT t3.data SEPARATOR ', ') AS t3properties
FROM
  (SELECT DISTINCT id FROM table1 WHERE data LIKE "a") AS t1
  JOIN table2 AS t2 ON t1.id=t2.id
  JOIN table3 AS t3 ON t1.id=t3.id
GROUP BY t2.data, t3.data

Для более чем двух таблиц это не свернет все значения table2.data и table3.data для одного идентификатора в одну строку. Я также попытался сделать это как последовательность вложенных выборок, но это просто заставило запрос выполняться очень долго.

Я понятия не имею, как называется этот тип выбора, поэтому я совершенно не могу найти, как эта проблема была решена (вероятно, давным-давно). Если кто-нибудь знает, как это сделать или что искать, чтобы узнать, как это сделать в другом месте, я был бы очень признателен за любую помощь.

обновление

Полный вложенный выбор, который я пробовал, используя мои настоящие имена таблиц, выглядит следующим образом:

SELECT
  keb.id AS id,
  english,
  reading,
  GROUP_CONCAT(DISTINCT keb.data SEPARATOR ', ') AS kanji
FROM
  (SELECT
     eng.id AS id,
     english,
     GROUP_CONCAT(DISTINCT reb.data SEPARATOR ', ') AS reading
   FROM
     (SELECT
        DISTINCT id,
        GROUP_CONCAT(DISTINCT data SEPARATOR ', ') AS english
      FROM dictionary_eng
      WHERE (data LIKE "%tiger%")
      GROUP BY id
      ORDER BY id
     ) AS eng
     JOIN dictionary_reb AS reb ON eng.id=reb.id
   GROUP BY eng.id
   ORDER BY eng.id
  ) AS reb
  JOIN dictionary_keb AS keb ON reb.id=keb.id
  GROUP BY keb.id
  ORDER BY keb.id

все определения таблицы:

(id INT NOT NULL, data TEXT)

Нет столбцов INDEX, мотивированных в основном тем, что это данные словаря JP-> EN. Индексирование английской таблицы в основном делает возможным индексирование целых абзацев текста, что не идеально, и MySQL не может индексировать японский язык из-за ограничения минимальной длины индекса (минимум 3 буквы имеют смысл для английского, но большинство японских слов состоят только из одного или двух глифов, поэтому они никогда не индексируются). Я мог бы установить таблицу идентификаторов в качестве индекса, но, поскольку это уже INT, кажется, не имеет особого смысла.

(первичных ключей также нет, поскольку идентификаторы не являются уникальными идентификаторами в этих таблицах)

MySQL объясняет мой вложенный выбор следующим образом:

+----+-------------+----------------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table          | type | possible_keys | key  | key_len | ref  | rows   | Extra                           |
+----+-------------+----------------+------+---------------+------+---------+------+--------+---------------------------------+
|  1 | PRIMARY     | <derived2>     | ALL  | NULL          | NULL | NULL    | NULL |     77 | Using temporary; Using filesort |
|  1 | PRIMARY     | keb            | ALL  | NULL          | NULL | NULL    | NULL | 185054 | Using where; Using join buffer  |
|  2 | DERIVED     | <derived3>     | ALL  | NULL          | NULL | NULL    | NULL |     77 | Using temporary; Using filesort |
|  2 | DERIVED     | reb            | ALL  | NULL          | NULL | NULL    | NULL | 178085 | Using where; Using join buffer  |
|  3 | DERIVED     | dictionary_eng | ALL  | NULL          | NULL | NULL    | NULL | 262929 | Using filesort                  |
+----+-------------+----------------+------+---------------+------+---------+------+--------+---------------------------------+

(размеры таблиц dictionary_eng: 268512 записей, dictionary_keb: 182366 записей, dictionary_reb: 172755 записей)

Ответы [ 2 ]

1 голос
/ 18 ноября 2011

Попробуйте это:

SELECT
    T1.id,
    T1.properties AS t1properties,
    T2.properties AS t2properties,
    T3.properties AS t3properties
FROM
(
    SELECT id, GROUP_CONCAT(DISTINCT data SEPARATOR ', ') AS properties
    FROM table1
    GROUP BY id
) T1
JOIN
(
    SELECT id, GROUP_CONCAT(DISTINCT data SEPARATOR ', ') AS properties
    FROM table2
    GROUP BY id
) T2
ON T1.id = T2.id
JOIN
(
    SELECT id, GROUP_CONCAT(DISTINCT data SEPARATOR ', ') AS properties
    FROM table3
    GROUP BY id
) T3
ON T2.id = T3.id
0 голосов
/ 18 ноября 2011

Я не mysql человек, но, глядя на это, вы можете сделать следующее:

1. Создайте три отдельных представления, используя GROUP_CONCAT
vTable01Props
vTable02Props
vTable03Props
2. Создайте UNION-представление различных идентификаторов из таблиц Table1, Table2 и Table3
3. Напишите запрос, который СЛЕДУЕТ ОБЪЕДИНИТЬ эти четыре представления по ID

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...