(Быстрый) поиск несмотря на наследование строк - PullRequest
1 голос
/ 04 марта 2012

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

id (INT)
parent_id (INT)
col0
col1
col2

Например, в этой таблице сохранены следующие записи:

1     NULL   abc     def     NULL
2     1      test    NULL    NULL
3     1      NULL    NULL    xyz

Теперь я быискать во всех строках A, в которых нет строк B, указывающих на них (B.parent_id = A.id).Кроме того, значения строки должны быть либо теми, что присутствуют в текущей строке, либо, если есть NULL, следует учитывать значения родительского элемента.

Чтобы проиллюстрировать мои требования, я хотел бы показать некоторыепримеры:

SEARCH(col0=test) => #2 (#1 has some children, #3.col0 = abc (inherited from #1))
SEARCH(col1=def) => #2, #3 (#1 has some children)
SEARCH(col2=xyz) => #3 (#1 has some children, #2.col2 = NULL (inherited from #1))

Кто-нибудь знает, как реализовать такой поиск в MySQL?

Ответы [ 2 ]

2 голосов
/ 04 марта 2012

Наиболее чистым решением, вероятно, было бы создание представления с объединением родительского и дочернего столбцов:

CREATE VIEW foo
AS SELECT
  c.id AS id,
  COALESCE(c.col0, p.col0) AS col0,
  COALESCE(c.col1, p.col1) AS col1,
  COALESCE(c.col2, p.col2) AS col2
FROM table AS c
  LEFT JOIN table AS p ON p.id = c.parent_id
WHERE NOT EXISTS
  (SELECT * FROM table AS x WHERE c.id = x.parent_id)

Затем вы можете писать запросы к этому представлению, как если бы это была обычная таблица.1005 * Однако, как отмечает Мантриур, не будет очень эффективным.Если таблица меняется не очень часто, вы можете использовать CREATE TABLE ... SELECT вместо CREATE VIEW, чтобы создать фактическую таблицу, содержащую объединенные данные, и создать некоторые индексы для нее, чтобы ее можно было эффективно запрашивать.Однако такая таблица не будет отслеживать изменения в исходной таблице, как это делает представление.

В принципе, вы можете использовать триггеры (или логику приложения) для обновления объединенной таблицы в реальном времени в качестве базовой таблицы.изменения, но это может легко стать сложным и склонным к ошибкам.К сожалению, в то время как некоторые другие РСУБД поддерживают материализованные представления , которые по сути являются способом сделать это автоматически, в настоящее время MySQL этого не делает. Flexviews , хотя я сам не пробовал.)

2 голосов
/ 04 марта 2012
SELECT
# if first table has no value, use parent table
IF(t1.col0, t1.col0, t2.col0) as virtcol0,
IF(t1.col1, t1.col1, t2.col1) as virtcol1,
IF(t1.col2, t1.col2, t2.col2) as virtcol2
FROM table as t1
LEFT JOIN table as t2 ON t1.parent_id = t2.id
LEFT JOIN table as t3 ON t1.id = t3.parent_id
# t3 would be children of t1. We don't want t1 to procreate. :)
WHERE t3.id IS NULL
# Your actual search goes here:
AND virtcol0/1/2 = whatever

Быстрая? Нет. Лучшее использование индекса, которое вы можете получить из этого, - это соединения с id / parent_id.

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

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