Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите разобраться с запросом  [new]
nikonn
Member

Откуда:
Сообщений: 8
В БД есть 3 таблицы:

Первая содержит адреса (32112, 'ул. Центральная, д.1, корп.1')

CREATE TABLE "addresses" (
	"ADDRESS_ID" INT NOT NULL,
	"ADDRESS" VARCHAR(250) NOT NULL
    );

Вторая содержит связи между адресами и ключевыми словами в адресе. (32112, 1; 32112, 2;...)

CREATE TABLE "keys_addresses" (
	"ADDRESS_ID" INT NOT NULL,
	"WORD_ID" INT NOT NULL
    );

Третья содержит ключевые слова (1, 'ул'; 2, 'Центральная';...)

CREATE TABLE "words_addresses" (
	"WORD_ID" INT NOT NULL,
	"KEYWORD" VARCHAR(22) NOT NULL
    );

В программе принимается адрес, разбирается на ключевые слова и строится запрос.
Проблема в том, что я никак не могу понять как написать его так, чтобы он возвращал только те адреса, в которых присутствуют ВСЕ заданные ключевые слова.

Моих знаний хватило только на такого рода запрос -

SELECT dbo.addresses.ADDRESS 
FROM dbo.addresses
INNER JOIN dbo.keys_addresses ON (dbo.address.ADDRESS_ID = dbo.keys_addresses.ADDRESS_ID)
INNER JOIN dbo.words_addresses ON (dbo.words_addresses.WORD_ID = dbo.keys_addresses.WORD_ID)
WHERE dbo.words_addresses.KEYWORD IN ('ул', 'Центральная');


Логично, что этот запрос возвращает все адреса, в которых содержится хотя бы одно из этих ключевых слов...
Помогите пожалуйста советом...
13 май 12, 21:52    [12546890]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
locky
Member

Откуда: Харьков, Украина
Сообщений: 62034
nikonn,

1. Выбрать те адреса, которые не содержат хотя бы одного ключевого слова
2. из всех адресов вычесть те адреса, которые получились в п.1
13 май 12, 21:57    [12546913]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
qwerty112
Guest
SELECT dbo.addresses.ADDRESS 
FROM dbo.addresses
INNER JOIN dbo.keys_addresses ON (dbo.address.ADDRESS_ID = dbo.keys_addresses.ADDRESS_ID)
INNER JOIN dbo.words_addresses ON (dbo.words_addresses.WORD_ID = dbo.keys_addresses.WORD_ID)
WHERE dbo.words_addresses.KEYWORD IN ('ул', 'Центральная');
group by dbo.addresses.ADDRESS
having count(*)=2
13 май 12, 21:58    [12546923]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
nikonn
Member

Откуда:
Сообщений: 8
locky
nikonn,

1. Выбрать те адреса, которые не содержат хотя бы одного ключевого слова
2. из всех адресов вычесть те адреса, которые получились в п.1


Большое спасибо за совет, но он мне не совсем подходит учитывая кол-во адресов (~25млн) и связей (> 100млн).

qwerty112
SELECT dbo.addresses.ADDRESS 
FROM dbo.addresses
INNER JOIN dbo.keys_addresses ON (dbo.address.ADDRESS_ID = dbo.keys_addresses.ADDRESS_ID)
INNER JOIN dbo.words_addresses ON (dbo.words_addresses.WORD_ID = dbo.keys_addresses.WORD_ID)
WHERE dbo.words_addresses.KEYWORD IN ('ул', 'Центральная');
group by dbo.addresses.ADDRESS
having count(*)=2


Вот, то что я искал! Огромное спасибо!!! Не заработало, но направление то самое!!!
Вот что получилось -

SELECT dbo.addresses.ADDRESS
FROM dbo.addresses
WHERE dbo.addresses.ADDRESS_ID IN
(
	SELECT dbo.keys_addresses.ADDRESS_ID
	FROM dbo.keys_addresses
	INNER JOIN dbo.words_addresses ON (dbo.words_addresses.WORD_ID = dbo.keys_addresses.WORDID)
	WHERE wordsadr.WORDID IN 
	(
		SELECT dbo.words_addresses.WORD_ID 
		FROM dbo.words_addresses
		WHERE dbo.words_addresses.KEYWORD IN ('ул', 'Центральная')
	)
	GROUP BY dbo.keys_addresses.WORD_ID
	HAVING COUNT(*) = 2
)


Работает относительно быстро. Если есть советы по оптимизации -
13 май 12, 22:36    [12547112]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
qwerty112
Guest
а "не заработало", случайно, не из-за того, что я не убрал ; ?
qwerty112
SELECT dbo.addresses.ADDRESS 
FROM dbo.addresses
INNER JOIN dbo.keys_addresses ON (dbo.address.ADDRESS_ID = dbo.keys_addresses.ADDRESS_ID)
INNER JOIN dbo.words_addresses ON (dbo.words_addresses.WORD_ID = dbo.keys_addresses.WORD_ID)
WHERE dbo.words_addresses.KEYWORD IN ('ул', 'Центральная');
group by dbo.addresses.ADDRESS
having count(*)=2

должно "работать"...
13 май 12, 22:59    [12547213]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
invm
Member

Откуда: Москва
Сообщений: 9833
nikonn, то, что вам требуется, называется реляционным делением. Реализовать можно различными способами. Например, см. тут.
13 май 12, 23:34    [12547332]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
nikonn
Member

Откуда:
Сообщений: 8
qwerty112
а "не заработало", случайно, не из-за того, что я не убрал ; ?
qwerty112
SELECT dbo.addresses.ADDRESS 
FROM dbo.addresses
INNER JOIN dbo.keys_addresses ON (dbo.address.ADDRESS_ID = dbo.keys_addresses.ADDRESS_ID)
INNER JOIN dbo.words_addresses ON (dbo.words_addresses.WORD_ID = dbo.keys_addresses.WORD_ID)
WHERE dbo.words_addresses.KEYWORD IN ('ул', 'Центральная');
group by dbo.addresses.ADDRESS
having count(*)=2

должно "работать"...


Эту очепятку я сразу поправил. Адреса извлекались, но не правильные. Как и в самом начале.

invm
nikonn, то, что вам требуется, называется реляционным делением. Реализовать можно различными способами. Например, см. тут.


Спасибо, очень познавательно!
14 май 12, 00:26    [12547438]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
MasterZiv
Member

Откуда: Питер
Сообщений: 34705
nikonn,

С count запрос только лишь условно-правильный. Некоторые слова могут встречаться несколько раз.

Тебе надо в твоем запросе заменит in на равенство, и повторить эту серию join-ов несколько раз для каждого ключевого слова по разу.
14 май 12, 00:27    [12547439]     Ответить | Цитировать Сообщить модератору
 Re: Помогите разобраться с запросом  [new]
nikonn
Member

Откуда:
Сообщений: 8
MasterZiv
nikonn,

С count запрос только лишь условно-правильный. Некоторые слова могут встречаться несколько раз.

Тебе надо в твоем запросе заменит in на равенство, и повторить эту серию join-ов несколько раз для каждого ключевого слова по разу.


Спасибо за совет, утром попробую.
14 май 12, 02:07    [12547592]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить