#mysql #database #database-design
#mysql #База данных #database-design
Вопрос:
я попытаюсь объяснить проблему.
У меня есть такая структура:
offers
--------------
id_offer|offer|company
1 | web programmer| Microsoft
2 | web programmer| Microsoft
tags
--------------
id_tags | tags
1 | php
2 | js
3 | asp
offers_has_tags
---------------
offers_id_offer (fk) | tags_id_tags (fk)
1 | 1
1 | 2
1 | 3
2 | 1
2 | 2
Если я использую систему, подобную Stackoverflow
, где каждый заголовок вопроса уникален, с приведенным ниже кодом проблем нет. Но если у меня могут быть разные предложения с одинаковым названием и с одним и тем же владельцем, я не могу сделать WHERE offers = ?
,
Итак, мне нужен другой подход к выбору конкретной работы. Не может быть названием и не может быть владельцем название, потому что у одного и того же владельца могут быть разные предложения с одинаковым названием.
INSERT INTO `offers_has_tags` (
offers_id_offer,
tags_id_tags
)
VALUES (
(SELECT id_offer FROM offers WHERE offer = ?), //here
(SELECT id_tags FROM tags WHERE tags = ?))
Как я могу выбрать предложение, если существует более одного предложения с одинаковым названием и одним и тем же владельцем?
Комментарии:
1. Что ты здесь пытаешься сделать?
2. здесь? я пытаюсь помочь..
3. Ничто не мешает вопросу StackOverflow иметь тот же заголовок, что и у другого.
4. Я получаю предупреждающее сообщение, когда я использую тот же заголовок другого предыдущего вопроса другим пользователем: вопрос с таким названием уже существует; пожалуйста, будьте более конкретными.
Ответ №1:
Простой ответ: невозможно получить ровно одну строку из таблицы, если ваше предложение where не фильтрует строки по столбцам PK.
Не на 100% ясно, чего вы пытаетесь достичь. Однако первичный ключ используется для однозначной идентификации строки. Это означает, что в этом случае вы должны использовать offer_id в предложении where (в вашем операторе insert в исходном вопросе).
Я предполагаю, что у вас есть какой-то пользовательский интерфейс перед этим — почему ваш пользовательский интерфейс не отправляет offer_id в код доступа к данным вместо имени предложения?
Но, если вы хотите вставить все предложения с одинаковым именем и владельцем в offer_has_tag, попробуйте это (это синтаксис T-SQL, но, насколько я помню, он также должен работать с MySQL):
INSERT INTO `offers_has_tags` (
offers_id_offer,
tags_id_tags
)
SELECT id_offer, (SELECT id_tags FROM tags WHERE tags = ?)
FROM offers WHERE offer = ? AND company = ?)
Пожалуйста, обратите внимание, что вы должны использовать id_tags вместо имени тега в своих запросах. Используйте только описательные атрибуты при фильтрации списка для конечного пользователя. В противном случае используйте столбцы первичного ключа.
Комментарии:
1. @Daniel, я только что прочитал эти комментарии, и мне жаль, но никто не сможет вам помочь из-за предложения, выделенного жирным шрифтом в моем ответе. Просто невозможно получить только одну строку, если значение, которое вы фильтруете, не уникально (и чтобы убедиться, что оно уникально, столбцы, которые вы используете в предложении where, должны быть в PK или уникальном индексе). Или я все еще не понимаю, чего вы пытаетесь достичь.
2. да, это проблема. заголовок не может быть уникальным, так как я могу отфильтровать предложение? может быть, отметка времени?
3. Если один владелец не может опубликовать больше предложений с тем же именем, поместите уникальный индекс в поле предложения. В противном случае, возможно, вы хотите применить бизнес-правило, согласно которому за один период времени может быть размещено только одно предложение от одного владельца (дополнительные столбцы ValidFrom, ValidTo), тогда вы можете использовать эти фильтры для дополнительной фильтрации. Но, если вы добавите только столбец timestamp, то у вас будет в основном то же самое: либо вы должны знать id_offer, либо timestamp. Или вы просто хотите использовать последнее? Тогда вы можете воспользоваться timestamp .
4. да, вероятно, имеет смысл удалить id_offer и использовать только временную метку как PK. С помощью метки времени и заголовка я могу выбрать конкретное предложение (даже с тем же названием). спасибо 🙂
Ответ №2:
Не могли бы вы быть немного более конкретными? В какой ситуации вы выполняете sql, с какой целью и каким образом приводятся аргументы? Может быть, опубликовать код, который находится перед этими операторами. Это может помочь ответить на ваш вопрос. В данный момент мне интересно, почему так сложно получить в результате более одного случая?
Комментарии:
1. чтобы уточнить. Два предложения с одинаковым названием и одним и тем же владельцем могут быть помечены разными ключевыми словами. В моем примере (код sql), если я это сделаю
WHERE offer = "web programmer"
, я получу два результата, поэтому я помечу два предложения одинаковыми тегами. вы понимаете, что я имею в виду?2. На самом деле нет. Я задал еще несколько вопросов, на которые до сих пор нет ответа; довольно сложно понять, какова цель всего этого. Единственное, что я представляю сейчас, это то, что у вас есть веб-сайт, и вы хотите показать все предложения о работе с определенным названием и конкретными тегами или что-то в этом роде?
3. Нет. По сути, на данном этапе единственное, что я хочу, это пометить предложения. пользователь вводит заголовок предложения и присваивает теги. Проблема заключается исключительно в выборе уникального предложения, которое может иметь одного и того же владельца и тот же заголовок. как я могу выбрать его в подзапросе?
4. Это заменяет ответ Филипа; вы говорите о выборе уникального предложения. Это означает, что у предложения должен быть уникальный атрибут, такой как id (например, key), и что ваш поиск в вашем SQL-запросе для этого уникального идентификатора. id_offer и id_tags должны быть уникальными значениями ключа, и вы можете искать определенный идентификатор. Это вернет одну строку.
5. но, чтобы выбрать идентификатор, который будет уникальным, мне нужен другой атрибут для поиска. Единственное, что я помню, это заголовок временная метка. Вы предлагаете какой-либо другой подход?