Справка по Delphi 7, ADO и SQL Access SQL Statement - Part Deuce - PullRequest
0 голосов
/ 21 декабря 2010

Мне нужна помощь, чтобы понять, почему мой SQL не работает.Или, если мне нужно написать по-другому, чтобы получить результаты, которые мне нужны.Как следует из названия, я использую Delphi 7 с компонентами ADO и базу данных MS Access 2000.Вы можете увидеть структуру моей таблицы из первой части здесь:
Справка по Delphi 7, ADO и MS Access SQL Statement

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

выберите * из (знание K
внутреннее объединение Knowledge_keywords KKW для KKW.knowledgeid = K.id)
внутреннее объединение ключевых слов KW для KW.id = KKW.keywordid
where (KW.keyword = 'job') AND (KW.keyword = 'task')

Однако это не возвращает и не приводит к результатам, когда явно есть оба этих слова в таблице Knowledge_keywords стот же идентификатор знаний.

Однако, если я делаю тот же SQL с ИЛИ вместо И, я получаю две ожидаемые записи

select * from (знание K
внутреннее объединение знание_ключевых слов KKW на KKW.knowledgeid = K.id)
ключевые слова внутреннего соединения KW для KW.id = KKW.keywordid
где (KW.keyword = 'job') И (KW.keyword = 'task')

спасибо за любую помощь

Ответы [ 2 ]

5 голосов
/ 21 декабря 2010

Подумайте об этом следующим образом: сколько записей в Knowledge_Keywords, для которых это правда оба , что ключевое слово = 'работа' И ключевое слово = 'задача'. Таких записей нет. Когда вы используете AND, вы запрашиваете записи, которые удовлетворяют обоим первому условию И второму условию одновременно. Когда вы используете ИЛИ, вы запрашиваете записи, которые удовлетворяют одному условию ИЛИ другому (или обоим).

В этом случае ИЛИ выражает то, что вы хотите. И выражает что-то другое.

Вы также можете использовать KW.keyword IN ('job', 'task'), который является более кратким и, возможно, более понятным.

2 голосов
/ 21 декабря 2010

Я думаю, что первый запрос не даст никакого результата, не так ли? Это потому, что «и» в речи отличается от «и» в программировании. Когда вы говорите, что вам нужны ключевые слова «работа» и «задача», вы на самом деле имеете в виду, что вам нужны строки, где ключевым словом является «работа» или «задача». Ключевое слово не может быть одновременно «заданием» и «заданием», поэтому запрос не будет возвращать никаких строк. Вы можете заменить OR на IN в виде

WHERE KW.Keyword in ('job', 'task')

Но это, вероятно, не даст вам желаемого результата. Я подозреваю, что вам нужно найти статьи, которые соответствуют обоим ключевым словам. Чтобы проверить, есть ли в базе знаний оба ключевых слова, вам может понадобиться что-то вроде этого (хотя я не уверен, что Access принимает это:

    select
      * 
    from 
      knowledge K
    where
      exists
          (select 'x' from
            knowledge_keywords KKW
            inner join keywords KW on KW.id = KKW.keywordid
          where
            KKW.knowledgeid = K.id and
             KW.keyword = 'job') 
      and exists
          (select 'x' from
            knowledge_keywords KKW
            inner join keywords KW on KW.id = KKW.keywordid
          where
            KKW.knowledgeid = K.id and
             KW.keyboard = 'task') and

[править]

Другой подход, который может работать лучше в Access (извините, я не могу его проверить), заключается в использовании такого подсчета. Я сделал небольшое предположение о полях в K для этого примера. Таким образом, вы присоединяете каждое ключевое слово в списке. Для статьи базы знаний, в которой есть и «задание», и «задание», сначала будет возвращено две строки. Эти строки затем группируются по полям Знания, и строки подсчитываются. Только статьи, количество которых соответствует общему количеству ключевых слов, возвращаются.

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

    select
      K.ID,
      K.Title,
      K.Content
    from
      knowledge K
      inner join knowledge_keywords KKW on KKW.knowledgeid = K.id)
      inner join keywords KW on KW.id = KKW.keywordid
    where 
      KW.keyword in ('job', 'task')
    group by
      K.ID,
      K.Title,
      K.Content
    having
      count(*) = 2 /* Number of keywords */
...