2010-05-20 1 views
3

У меня есть 6 таблиц, назовем их a, b, c, d, e, f. Теперь я хочу искать все столбцы (кроме столбцов ID) всех таблиц для определенного слова, скажем, «Джо». Я сделал это, я сделал INNER JOINS поверх всех таблиц, а затем использовал LIKE для поиска столбцов.Как избежать декартового продукта в запросе INNER JOIN?

INNER JOIN 
... 
ON 
INNER JOIN 
... 
ON.......etc. 
WHERE a.firstname 
~* 'Joe' 
OR a.lastname 
~* 'Joe' 
OR b.favorite_food 
~* 'Joe' 
OR c.job 
~* 'Joe'.......etc. 

Результаты верны, я получаю все найденные мной колоды. Но у меня также есть какой-то декартовой продукт, я получаю две или более строк с почти одинаковыми результатами.

Как я могу избежать этого? Я хочу, чтобы каждая строка была только одна, так как результаты должны отображаться в веб-поиске.

UPDATE

Я первый попытался выяснить, если SELECT DISTINCT вещь будет работать, используя это заявление: pastie.org/970959 Но она по-прежнему дает мне декартово произведение. Что случилось с этим?

+0

Укажите, пожалуйста, какой db вы используете. – hgulyan

ответ

2

попытка SELECT DISTINCT?

+0

Даже если это SQL Server? – hgulyan

+1

ms sql server все еще имеет отличный выбор, не так ли? – oedo

+0

Спасибо за подсказку. – flhe

2

На каком состоянии вы JOIN это tables? У вас есть foreign keys или что-то в этом роде?

Возможно, вы должны найти это слово на каждом столе отдельно?

+0

У меня есть отношения между таблицами, поэтому я делаю INNER JOIN в таблице person_has_job и оттуда в таблицу заданий. – flhe

1

Какой сервер вы используете? Microsoft SQL Server имеет полнотекстовую функцию индекса (я думаю, что у других тоже есть что-то подобное), которая позволяет искать ключевые слова гораздо менее ресурсоемким способом.

Также рассмотрите возможность использования UNION вместо соединения таблиц.

+0

Это сервер postgresql. – flhe

0

Не видя своих таблиц, я могу только предположить, что здесь происходит, так как у вас есть отношения «один ко многим». Вероятно, вы хотите сделать все в подзапросе, выбрать отдельные идентификаторы, а затем получить данные, которые хотите отобразить по идентификатору. Что-то вроде:

SELECT a.*, b.* 
FROM (SELECT DISTINCT a.ID 
     FROM ... 
     INNER JOIN ... 
     INNER JOIN ... 
     WHERE ...) x 
INNER JOIN a ON x.ID = a.ID 
INNER JOIN b ON x.ID = b.ID 

Несколько вещей, однако, отметить:

  • Это будет sloooow и вы, вероятно, хотите использовать полнотекстовой поиск вместо (если РСУБДА опоры Это).

  • Возможно, быстрее выполнить поиск по каждой таблице отдельно, а не сначала соединить все в картезианском продукте, а затем фильтровать с помощью OR.

+0

Это может быть решение, я попробую. Благодаря! – flhe

+0

Хорошо, тогда я посмотрю на полнотекстовый поиск postgresql. – flhe

+0

Сначала я попытался выяснить, будет ли работа SELECT DISTINCT работать с использованием этого оператора: http://pastie.org/970959 Но он все еще дает мне декартовой продукт. Что случилось с этим? – flhe

0

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

Вы говорите, что хотите найти все таблицы для определенного слова, но вы, вероятно, захотите отделить результаты от соответствующих типов. Правильно? В противном случае веб-поиск не имеет большого смысла. Итак, если вы читаете «Джо», вы хотите увидеть людей, имеющих имя «Джо» и, например, компанию под названием «Спортивный зал Джо».Поскольку вы ищете разные объекты, чтобы разделить поиск на разные запросы.

Если вы действительно хотите сделать это в одном запросе, вам придется изменить структуру базы данных для размещения. Вам понадобится форма «таблица поиска», содержащая идентификатор объекта (PK) и тип сущности, а также список ключевых слов, которые вы хотите, чтобы этот объект был найден. Например:

EntityType, EntityID, Keywords 
------------------------------ 
Person,  4,  'Joe', 'Doe' 
Company, 12,  'Joe''s Gym', 'Gym' 

Что-то в этом роде?

Тем не менее, отличается тем, что ваш поиск возвращает только один тип сущности, скажем Личность, и вы хотите вернуть Лица, для которых вы получаете удар по этому ключевому слову (в любой связанной таблице с этим Лицом). Затем вам нужно будет выбрать все поля, которые вы хотите показать, и сгруппировать по ним, оставив поля, в которых вы ищете. Включение их неизбежно приводит к декартовому продукту.

Я, кстати, здесь всего лишь мозговой штурм. Надеюсь, это поможет.