Доска объявлений - Оптимизация базы данных

Этот вопрос следует из этого Question

Проект и проблема

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

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

Я был бы признателен за вклад в дизайн платы в целом и, в частности, способы улучшения структуры базы данных для облегчения эффективных запросов и ускорения разработки этого приложения и будущего приложения

/p >

Бизнес-логика

Доска объявлений будет использоваться следующим образом

  • Публикация бюллетеней и ответов на бюллетени
    •   
    • Сотрудники или "пользователи" в офисах по всей стране смогут размещать сообщения на доске объявлений. Бюллетени должны быть отправлены в местоположение и категоризированы - я буду называть эти "бюллетени".  
    • Пользователи смогут отправлять любое количество ответов в любой бюллетень, и пользователи смогут ответить на их собственный бюллетень - я буду называть эти "ответы".
  • Бюллетени и ответы по рейтингам   
    1. Пользователи смогут либо "понравиться", либо "не нравится" бюллетеню или ответу, и общее количество симпатий или антипатий будет показано для каждого бюллетеня или ответа.
Просмотр доски объявлений и ответов
  •   
  • Бюллетени могут отображаться в хронологическом порядке.  
  • Пользователи могут сортировать бюллетени хронологически или хронологически по последнему ответу на этот бюллетень (дайте мне знать, если вам нужно больше объяснений)  
  • Когда выбран конкретный бюллетень, ответы на этот бюллетень будут отображаться в хронологическом порядке
-- phpMyAdmin SQL Dump
-- version 3.2.4
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Jan 16, 2011 at 06:44 PM
-- Server version: 5.1.41
-- PHP Version: 5.3.1

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Database: `bulletinboard`
--

-- --------------------------------------------------------

--
-- Table structure for table `bbs`
--

CREATE TABLE IF NOT EXISTS `bbs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bb_locations_id` int(11) NOT NULL,
  `bb_categories_id` int(11) NOT NULL,
  `users_id` int(11) NOT NULL,
  `title` varchar(255) NOT NULL,
  `content` text NOT NULL,
  `created_date` int(11) NOT NULL,
  `rank` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=87 ;

--
-- Dumping data for table `bbs`
--

INSERT INTO `bbs` (`id`, `bb_locations_id`, `bb_categories_id`, `users_id`, `title`, `content`, `created_date`, `rank`) VALUES
(83, 8, 28, 44, 'sdaf', 'asdfasdf', 1292712797, 0),
(84, 8, 28, 44, 'asdf', 'asdfasd', 1292875089, 0),
(86, 8, 28, 44, 'Robert is leaving', 'Robert is leaving and going back to the states ', 1294344916, 0);

-- --------------------------------------------------------

--
-- Table structure for table `bb_categories`
--

CREATE TABLE IF NOT EXISTS `bb_categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `description` varchar(255) NOT NULL,
  `list_order` varchar(255) NOT NULL,
  `admin` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=30 ;

--
-- Dumping data for table `bb_categories`
--

INSERT INTO `bb_categories` (`id`, `title`, `description`, `list_order`, `admin`) VALUES
(28, 'Travel', 'Rideshares, proposed trips etc', '1', 1);

-- --------------------------------------------------------

--
-- Table structure for table `bb_locations`
--

CREATE TABLE IF NOT EXISTS `bb_locations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `description` varchar(255) NOT NULL,
  `address` varchar(255) NOT NULL,
  `post_code` int(11) NOT NULL,
  `list_order` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;

--
-- Dumping data for table `bb_locations`
--

INSERT INTO `bb_locations` (`id`, `title`, `description`, `address`, `post_code`, `list_order`) VALUES
(8, 'Washington DC', 'asdkf', 'dsf', 0, 1);

-- --------------------------------------------------------

--
-- Table structure for table `bb_ratings`
--

CREATE TABLE IF NOT EXISTS `bb_ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bbs_id` int(11) NOT NULL,
  `users_id` int(11) NOT NULL,
  `like_id` int(2) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=68 ;

--
-- Dumping data for table `bb_ratings`
--


-- --------------------------------------------------------

--
-- Table structure for table `bb_replies`
--

CREATE TABLE IF NOT EXISTS `bb_replies` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `users_id` int(11) NOT NULL,
  `bbs_id` int(11) NOT NULL,
  `content` text NOT NULL,
  `created_date` int(11) NOT NULL,
  `rank` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=158 ;

--
-- Dumping data for table `bb_replies`
--

INSERT INTO `bb_replies` (`id`, `users_id`, `bbs_id`, `content`, `created_date`, `rank`) VALUES
(156, 44, 86, 'good ridance i say\r\n', 1294788444, 0),
(157, 44, 86, 'And stay away\r\n', 1294892751, 0);

-- --------------------------------------------------------

--
-- Table structure for table `bb_reply_ratings`
--

CREATE TABLE IF NOT EXISTS `bb_reply_ratings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bb_replies_id` int(11) NOT NULL,
  `users_id` int(11) NOT NULL,
  `like_id` tinyint(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=115 ;

--
-- Dumping data for table `bb_reply_ratings`
--


-- --------------------------------------------------------

--
-- Table structure for table `bb_sort_bys`
--

CREATE TABLE IF NOT EXISTS `bb_sort_bys` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(20) NOT NULL,
  `description` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Dumping data for table `bb_sort_bys`
--

INSERT INTO `bb_sort_bys` (`id`, `title`, `description`) VALUES
(1, 'Newest', 'Posts are sorted by their creation date'),
(2, 'Popular', 'Posts are sorted by the date of their lates reply, or by post date if they have now replies');

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(10) NOT NULL,
  `first_name` varchar(100) NOT NULL,
  `last_name` varchar(100) NOT NULL,
  `permission` int(1) NOT NULL,
  `bb_sort_bys_id` varchar(10) NOT NULL,
  `bb_locations_csv` varchar(255) NOT NULL,
  `defaultLocation` int(11) NOT NULL,
  `bb_categories_csv` varchar(255) NOT NULL,
  `total_bulletins` int(5) NOT NULL,
  `bulletins_per_page` int(5) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=45 ;

Ответ 1

Часть I

Пересмотрено 09 Дек. 10 01:00 EST

Посмотрел на ваш DDL. ОК. Нам нужно сделать шаг назад и сначала организовать вашу базу данных. Это позволит решить половину ваших проблем (ваш SQL будет прямым и быстрым, меньше индексов, никаких временных таблиц не требуется). Некоторое время я думал, ага, у вас есть свои столбцы, он должен быть стабильным, но нет никаких шансов. Сверху с нуля, хорошо. Посмотрите на эту диаграмму отношения сущностей (не используйте работу с моделью данных, которая является сущностями, отношениями и атрибутами), пока мы не получим правильные ER) и убедитесь, что она правильная.

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

  • Я думаю, ▶ этот пост ◀ может быть вам полезен, чтобы понять формальные этапы, которые должны соблюдаться; которые мы коротко замыкаем здесь.

  • Самое главное, полностью и полностью забыть о функции и любых требованиях к кодированию. Данные должны быть смоделированы независимо от приложения, просто как данные. Функциональное моделирование - это другая наука. Сначала сделайте одно право; затем получите другое право; и оба вместе играют красивые мелодии. Попытайтесь объединить их; одновременно выполняя обе задачи, и они даже не будут создавать полосу пригородного гаража.

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

Ссылки на красивые картинки в конце.

Извинения: редактирование не работает; под-нумерация несовместима

Закрытые проблемы

  • users.bb_locations_csv - отношение "много-ко-многим" между пользователями и местоположениями:
    • Каждый из этих элементов должен быть записью в дискретном столбце в дискретной строке
    • У одного пользователя может быть много местоположений, а в одном месте может быть много пользователей, многие из многих
    • Прочитайте ▶ этот пост ◀ для обсуждения того, как это обрабатывается, и на какой стадии он рассматривается
    • На этом логическом этапе это просто отношение n:: n, как я нарисовал, вы можете забыть об этом на данный момент, оно будет предоставлено просто, когда мы перейдем на физическую стадию.
    • Поверьте мне, я предоставил код, который не более сложный, чем ...WHERE IN () для вашей объявленной цели.
    • С другой стороны, если я сломаю пальцы, вы набираете еще медленнее, поэтому мне лучше не
    • Хорошо, ваше приложение основано на браузере, а страница динамическая (мой совет касался статических страниц, которые нужно трогать); поставьте флажки.
      .
  • users.bb_categories_csv - отношение "многие ко многим" между пользователями и категориями
    • То же.
      .
  • Подтверждено: бюллетень (bbs) не существует без пользователя; пользователь выпускает бюллетень и запускает весь цикл; затем приглашает ответы и рейтинги.

    3.1 Подтверждено: на самом деле существует только одна доска объявлений, и она не существует как Вещь в базе данных.

    3.2 Подтверждено: что в организации никогда не будет более одной доски объявлений, а классификации и категоризации будут надлежащим образом обработаны таблицей/функцией категории

  • Удалено.

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

  • Исключен.

  • Замечания. Решено.

7.1. Для каждого отдельного бюллетеня, представленного другим пользователем, каждый пользователь может отправлять более одного ответа.

7,2. Для каждого отдельного бюллетеня, представленного пользователем, этот пользователь может опубликовать один или несколько ответов.

7,3. Удаляется.

7.4. Удаляется.

Модель данных теперь позволяет получать более одного ответа на пользователя в бюллетене; включая пользователя, отправившего бюллетень.

.
8. Подтверждено: каждый пользователь может опубликовать не более одного рейтинга в бюллетене (который может быть отменен/изменен)
.
9. Подтверждено: каждый пользователь может опубликовать не более одного рейтинга до ответа (меньше)

10,1. Дано: имя пользователя поступает из организации и является уникальным именем, которое идентифицирует сотрудников. Например, электронная почта - имя пользователя@organisation.org - проверка подлинности выполняется с помощью ldap, и это необходимо для подключения другой информации о сотрудниках.

  • Подтверждено: UserName - отличный идентификатор

10,2. Подтверждено: FirstName, LastName... BirthPlace и т.д. Остаются как (традиционные) столбцы для обеспечения People не дублируются.
.
11. Учитывая: В настоящий момент мы можем идентифицировать наши офисы случайными именами, которые обычно известны внутри организации, поскольку у нас есть только три основных офиса и многие ветки на местах. Так что примерами будут Вашингтонский округ Колумбия или полевой офис виргинии. В целом я думаю, что мы постараемся сохранить общее количество ниже 20. Я хочу записать точный адрес каждого местоположения, а также потому, что это можно использовать для уникальной идентификации офисов для пользователей.

  • При условии: StateCode+Town как ПК; IsMainOffice как булево.

.
12. Подтверждено: Description и Name для Category. .
13. Учитывая: пользователи не смогут отправлять сообщения в некоторые категории. Только пользователи с достаточно высокими правами будут иметь право размещать сообщения в определенных категориях.

  • При условии: Permission в User, Location, Category - это метод оценки таких прав.

.
14. Подтверждено: Location.Administrator - UserId администратора для Location.
.
15. Учитывая: там будет только необходимость в подобной или нелюбовь. Я не думаю, что должна быть нейтральная позиция, потому что это то же самое, что просто не голосовать? Liking кажется более актуальным для ответов на бюллетень, в которых должно быть честно. То есть, я вижу ваш ответ и вместо того, чтобы писать свои собственные, я просто соглашусь с вами - существующая доска объявлений является скорее социальным аспектом в организации, и я думаю, что симпатия, неприязнь/согласие и несогласие создают противоречие, которое поощряет участие, Однако симпатия или неприятие бюллетеня не всегда могут быть полностью уместными.

15.1 При условии: Like как boolean в BulletinRating и ResponseRating. Это потребует интерпретации при каждом доступе.
15,2. Когда он больше не является логическим, его можно изменить на RatingCode и реализовать как таблицу Lookup. Затем имена определяются Joins, а интерпретация исключается. Я нарисовал это в первой модели данных, чтобы вы могли видеть, что я имел в виду 15,3. Удалено во второй модели данных.
.
16. Подтверждено: каждый пользователь имеет домашний Location (кроме списка Locations, который им интересен).
.
17. Подтверждено: Permission согласно (13).
.
18. Подтверждено: в соответствии с моделью данных могут потребоваться дополнительные разрешения.

18,1. Если вы сделаете это сейчас, вам не придется беспокоиться о том, когда организация решает помешать определенному Person от размещения Responses или Bulletins или оценить их; и хочет, чтобы эта функция была реализована вчера.

18,2. Даже если вы не реализуете его, оставляйте пробелы между значениями, которые вы реализуете.
.
19 Подтверждено: a Bulletin о a Location.

19,1. Подтверждено: нет Bulletins без Location

19,2. Подтверждено: нет Bulletins без Location.

19.3 Подтверждено: нет Bulletins без User (декларативный). Но до сих пор мы не можем ограничить это User; поэтому любой User может вставить a Bulletin для любого Location (вы можете ограничить его в коде, например, до Locations каждый User Is Interested In.

19.4 Подтверждено: нет BulletinRatings без Bulletin и рейтинга User.

19.5 Подтверждено: нет Responses без Bulletin.

19.4 Подтверждено: нет ResponseRatings без Response и рейтинга User.

19,7. Но может быть Users, Locations , and Категории`, независимо.

.
20. Если вы не возражаете, я предоставлю соглашения об именах и т.д. Они должны быть понятны, и значение будет отображаться только при запуске кодирования SQL. Пожалуйста, спросите, если что-то не так. Для начала все имена являются единственными. Смешанный случай легче читать (вы должны использовать капители для языка SQL).

20,1. Мой опыт table_name, в отличие от tableName, действительно являются техническими формами, и пользователям это не нравится; Соответствующий смешанный случай нравится всем. Это одна из тех вещей, которые невозможно изменить, поэтому выбирайте внимательно.
.
21. Для вашей необходимости группировать таблицы вместе, что хорошо, имейте в виду, что это физическая проблема. На уровне модели логических данных таблицы имеют нормальные имена, которые не загружаются физическими проблемами. Представьте, что на физических таблицах есть префикс с чем-то вроде (и, пожалуйста, используйте для этого капиталы):
- REF_ для справки (например, User) и справочных таблиц
- BUL_ для системы бюллетеня
.
Я не могу назвать таблицы заглавными буквами? Я не знаю, почему. Я не знаю, почему у меня нет имен таблиц в верхнем регистре. Это связано с использованием таблиц базы данных MyIsam?

Универсальное соглашение заключается в том, что язык SQL выражается в верхнем регистре; каждый инструмент отчета и администратора, который я когда-либо использовал, генерирует такой код SQL. Поэтому мы не можем использовать верхний регистр. Только нижний регистр или смешанный футляр. Таким образом, выбор сводится к table_name или TableName; нам нужен какой-то разделитель. По причинам, уже предоставленным, я настоятельно рекомендую смешанный случай, capiatlised, а не стиль OO с ведущим письмом, некапитализированным.

.
22. rank (все) можно получить непосредственно из базы данных (помните, не беспокойтесь о коде во время моделирования данных). Если вы храните его, это ошибка нормализации; дублированный столбец; который должен быть обновлен; который может выйти из строя с производным значением; который называется обновленной аномалией. Пятая нормальная форма исключает обновление аномалий. Это мой минимальный уровень нормализации, так что вы получите от меня.

22,1. Я вообще не вмешиваюсь в порядок сортировки или популярность; по сути, по звукам этого, вы не закрыли эту функциональность. Я беру избыточные данные, ранг столбца, вне, как часть процесса нормализации.

22,2. Здесь ▶ Quick Tutorial ◀ для оператора RANK() (как это обычно известно). Это не ANSI SQL; это расширение Oracle и MS. Однако это не требуется, если вы понимаете подзапросы, поэтому Sybase его не имеет. Я сомневаюсь, что у MySQL это есть, поэтому вам нужно обдумать это. Понимание Скалярных подзапросов является предварительным условием. Sybase синтаксис, так что ударяйте ваши полуколоны и т.д. Не стесняйтесь задавать конкретные вопросы.
.
Я никогда не видел такого подхода к записи Rank = (SELECT.... Это то же самое, что (SELECT...) как Rank?

Я отправил для этого отдельный ответ.

.
22,3. Нужно понять, почему, это не проблема. Только дети слепо следуют простым правилам, и вы, конечно, не один из них.
.
23. Подтверждено: users.total_bulletins является избыточным; он может быть получен. Удалены.
.
24. Все ваши ПК являются идентификаторами. Разве вы не устали от потери кода? Забудьте о прикреплении Id iot PK на все, что движется, узнайте, как ваши пользователи идентифицируют свои объекты; какие сущности действительно независимы, а другие зависят от независимых сущностей.

24,1. Никогда не используйте Id или любую такую ​​форму. Где это ПК, используйте полную форму.

24,2. Вызовите location_id, location_id, где бы он ни находился, включая таблицу PK. Исключение составляет то, когда вам нужно показать роль. Это станет ясно в модели данных.
.
25. У вас нет декларативной ссылочной целостности, нет Определенных внешних ключей. Это плохая новость по многим причинам. После того, как эти вопросы будут уточнены, добавьте их. DRI означает, что как можно больше, если не все, Integrity объявляется в SQL. Стандарт ISO/IEC/ANSI SQL позволяет это, но свободный конец рынка не обеспечивает стандарт и медленно догоняет. Это означает, что сервер не позволит добавить строку в таблицу FK, если PK не существует в родительской таблице. Недавно MySQL предоставил DRI для внешних ключей. Для FK см. ▶ этой статьи ◀.

25,1. Для ограничений CHECK и ПРАВИЛ вам придется реализовать их в коде.

Мои внешние ключи похожи на user-id (fk) = users.id(pk) Я не уверен, как добавить их в другие, что я сделал, но, безусловно, сделаю это, как только я знаю, как это сделать.

Это не добавление их в ваш db; это просто привязка столбцов в предложении WHERE на языке Манипуляции данными, а не в определении данных Languge. Добавляя их, чтобы они работали на уровне db/server, означает объявление их в DDL в соответствии с связанной статьей. Затем MySQL остановит строку, которая будет вставлена ​​в дочернюю таблицу (FK), где родительский PK не существует. Это Ссылочная целостность. Если он объявлен в DDL, он Декларативная ссылочная целостность.

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

Да, насколько я знаю. Подтверждено на ▶ на этом сайте ◀. Код, который я предоставил для подзапроса, использует DRI, поэтому мы можем проверить это и получить его с дороги раньше. Вы должны проверить свою версию MySQL.

Двадцать пять. Комментарии отмечены. Я не специалист по MySQL. Да, это те проблемы, которые вы должны выяснить сами. В общем, из моего изучения MySQL не имеет аналогов; для чего-то SQL-ish вам нужен InnoDB.

Но не позволяйте этому сдерживать вас. Теперь используйте Engine = MySQL, без декларативного SQL, и продолжайте работу с моделью данных и подзапросом. Работайте на InnoDB в фоновом режиме.

Чтобы быть ясным, DDL, который я предоставил, должен работать для MyISAM (и "ничего не делать" в отделе DRI, пока вы не получите InnoDB).

.
27. Учитывая: я переосмыслил требования к сортировке бюллетеней. Пользователи могут сортировать хронологически - легко, имеет смысл. Пользователи могут сортировать бюллетени по дате последнего ответа на бюллетень. Тогда мы можем забыть о ранге, и должно быть очень легко сортировать бюллетени хронологически к моменту их последнего ответа? Каковы ваши мысли.

Да. это разумно и довольно часто, большинство людей понимают хронологический порядок. Вам нужно будет использовать фильтры, которые они выбирают в окне поиска (выберите: Location или список, выберите: Category или список, выберите: My Bulletins или все).

Открытые проблемы

(ноль)

Модель данных

Хорошо, если у вас нет проблем с ERD и реализации всех закрытых проблем, я смоделировал данные и подготовил пятую модель данных 09 декабря 10 для вашего обзора. Я определенно нуждаюсь в гораздо больше отзывах, вопросах и т.д. Об этом. Я с трудом соглашаюсь с тем, что это сделано. Вероятно, лучше всего начать писать реальный код для проблемных областей.

Ссылки

▶ Ссылка на IDEF1X Обозначение ◀ Вам действительно нужно прочитать и понять это, прежде чем читать данные Модель.

▶ Ссылка на пятую модель данных бюллетеня ◀ Диаграмма связей сущностей на первой странице, а затем Модель данных.

  • Ключи довольно прямые IDEF1X (за исключением UserId, который я предоставил в качестве контрапункта); что означает кошелек Relational Keys. Не усилен и не оптимизирован для физических соображений. Прежде, чем вы будете на них нападать, сначала обратите внимание на них, зарегистрируйте их и оцените. Конечно, мы можем добавить Id iot ключи, но прежде чем мы это сделаем, дайте нам понять, что мы потеряем.

  • Обратите внимание на идентификаторы (сплошные строки) в соответствии с документом нотации. Позвоночник, позвонки системы Location ... Bulletin ... Response.

  • Обратите внимание, что Keys фактически реализуют многие бизнес-правила.

  • Обратите внимание на естественную иерархию, которую я отобразил. Посмотрите, есть ли для вас какой-либо смысл.

  • VerbPhrases действительно важны; см., если они что-то значат.

Комментарии re Первая модель данных и ответы

У меня есть вопрос, что первичный ключ местоположения будет использоваться для формирования дочернего первичного ключа? (к ним присоединяется сплошная линия). Я действительно не понимаю эту концепцию.

Да. PK для Location (над линией) составляет (StateCode, Town). Это PK два столбца вместе, составной ключ, переносится от Location до Bulletin в любом случае, как FK (полужирный). Мы дополнительно используем его для формирования Bulletin PK (над линией).

Если и когда нам нужен ключ Surrogate, мы добавим его. Пока мы разрабатываем идентификаторы. Итак, вопрос для размышления:

  • Что такое хороший идентификатор для бюллетеня?, что ваши пользователи естественно используют для определения бюллетеня...
  • "Вы видели бюллетень из Virginia FO вчера?",
  • "Салли из Вашингтона уверена, что пишет хорошие бюллетени" и т.д.

или почему эти отношения не существуют между пользователем и бюллетенем?

Ну, , что не может существовать между User and Bulletin, но существует a, пунктирная линия, означающая UserId, является FK в Bulletin (полужирный), но не используется для формирования его PK (ниже строки).

Или вы имеете в виду: пользователь является сильным идентификатором для Bulletin (и поэтому его следует использовать для формирования Bulletin PK, поэтому строка должна быть твердой)?

Fine. Отлично. Вот что такое моделирование идентификаторов. Это очищает область, которая мне не понравилась, потому что у нас были уникальные индексы. Это также решает мою проблему.

  • В соответствии с намерением, изложенным выше, поскольку я теперь показал рейтинг как таблицу, и каким будет рендеринг, один раз я удалю его

  • Я думаю, что разрешение должно быть Entity.

  • Bulletin Теперь PK (StateCode, Town, UserId, SequenceNo). Чтобы быть ясным, SequenceNo находится в пределах StateCode, Town, UserId: для 5-го бюллетеня Sally будет 5, re MO/Billngs FO.

  • Обратите внимание, что пользовательские настройки BulletinsPerPage и т.д. являются 1:: 1 с User, поэтому они находятся в User; таблица child будет неправильной.

  • Исправлены типографические ошибки.

Комментарии re Вторая модель данных и ответы

  • PKs для Bulletin и Response были изменены для отражения (7). BulletinNo и ResponseNo были заменены на BulletinDate и ResponseDate (который был CreatedDate), чтобы разрешить множественные ответы за User за Bulletin.

Комментарии к третьей модели данных и ответам

Доверяй тебе хороший перерыв.

  • Как минимум 30 лет назад (что я знаю), великаны в этой отрасли обсуждали это. Имена всегда единственные. Таблицы - существительные. VerbPhrases - это глаголы. Это не ограничивается соглашениями об именах db, оно применяется к документам, тезисам, диссертациям и т.д. В конце документа вы можете сделать 5 заключений, но заголовок раздела или главы как в ToC, так и в верхней части страницы это "Заключение".

    После борьбы с ними через Uni, как только я начал свою первую оплачиваемую работу по программированию и увидел важность правил в реальном мире, в отличие от теоретических аргументов, которые мы имели в колледже, я отказался от этого как пустая трата времени. Все это время и энергия, которые я потратил впустую, были освобождены, чтобы сделать продуктивную работу. С тех пор я не подвергаю сомнению гигантов; Я просто согласен. Что их разум больше моего. Это похоже на принятие стандартов или поведение в рамках закона или Бога. У меня нет действительно хороших причин делать что-то незаконное.

    В любом случае легкость объяснения (обсуждение, SQL, документация), поддерживаемая такими правилами, не может быть адекватно объяснена; поскольку вы пишете все больше и больше кода SQL, это станет ясно.

    Вы всегда можете использовать все, что захотите. Я поставляю только единственное.

  • Хорошо со мной.

    Но вам нужно иметь в виду, что эти два элемента в идентифицированной последовательности (ala non-PK Unique Index или Alternate Key) повсеместно необходимы для установления уникальности для Person. Удаление их приведет к двум вещам. Во-первых, вы больше не сможете идентифицировать уникальность в Users (и, следовательно, у вас могут быть повторяющиеся строки). Во-вторых, AK становится неидеальным, является ссылкой на инверсию.

  • Точка (в отличие от одного из сообщений), любой столбец, который равен 1:1 с User PK, должен находиться в User. Все настройки предпочтений. Поскольку мы очистили InterestedLocations и InterestedCategories, я знаю только только BulletinsPerPage; но я уверен, что есть другие. IsPreference2 является, например, boolean; NumPreference3 - это, например. целых чисел. И т.д. Вы можете сказать мне, каковы настоящие предпочтения.

    (Попробуйте это во множественном числе:... любой столбец, который равен 1:1 с Users PK, должен находиться в Users. Только не делает этого для меня, я получаю зависание на сломанный английский, и я немного ценен о моем родном языке.)

    Обновлена ​​модель данных.

  • Отлично. Дайте мне знать, когда вам будет удобно, и я дам вам физическую модель.

    Как насчет VerbPhrases?

Комментарии re 06 Dec 10 20:38 EST (Малые обновления)

.
28. Если имеется только одно вхождение PK в FK, конечно, имя столбца FK совпадает с именем столбца PK. Однако, когда имеется более одного окта FK (взгляните на ResponseRating), существует три UserIds), нам нужно их дифференцировать. В терминологии IDEF1X это называется Ролями. Роль User, который выпустил Bulletin, Issuer и так далее. Очевидно, что лучше использовать это имя и сохранить его согласованным по всей иерархии (не UserId в Bulletin), а затем, когда мы перейдем к Response, где их два, и требуется дифференцирование, измените его на IssuerId Я думал, что у вас может быть проблема с этим: на ранних этапах использование Issuer.UserId, так что абсолютно ясно, что это UserId как FK, а Роль Issuer; когда мы перейти к физической модели, упрощается до IssuerId.

Аналогично, у нас есть много столбцов DateTime (дата для краткости, если вам нравится, в противном случае Dtm), которые нужно дифференцировать.
.
29. Не был ли смысл документа IDEF1X Notation?

  • PK для каждой таблицы находится выше строки в указанном порядке.
  • Помните, что мы все равно переносим PK родительских таблиц, и если есть смысл, используя эти FK для формирования дочернего PK.
  • Для Bulletin:

    • Местоположение FK (StateCode, Town), для которого оно выдается
    • UserId эмитента
    • и DateTime было выпущено, чтобы сделать его уникальным.
    • поэтому (StateCode, Town, issuerId, BulletinDate) `
  • Чтобы удалить все ResponseRatings для этого Bulletin, используйте WHERE = в этих четырех столбцах Bulletin.

.
30. Потому что (State, Town) - это PK Location, несущий везде. И он является частью Bulletin PK, поэтому любые зависимые таблицы несут эти столбцы, потому что они несут Bulletin PK.

Ищите цветные вкладки (только эта версия)
.
32. Это фразы глаголов. Способ их чтения подробно описан в документе Notation. Кажется, у вас хорошая ручка. Очень важно правильно получить имена таблиц (и фразы глаголов), потому что смена происходит сложнее после реализации. Если вы скажете мне, что офис лучше, чем местоположение, это хорошо со мной.

Чтение: Управление активировано по бюллетеню

Не стесняйтесь поставлять другую глагольную фразу.
AFAIC, Office мертв для остальной части org и только оживает на их радаре (активируется) проблемой Bulletin.
Я понимаю, что это звучит глупо здесь, но на мгновение игнорируйте это, что-то вроде "Office выражает свою активность, рекламирует свою деятельность, выдавая Bulletin".

У вас есть опрос в модели данных датчика Mark, для некоторых хороших фраз.

Ранее мы определили, что (State, Town) является PK, Я оставлю это как Обратитесь к (38) для изменения.

.
33. Стоит обсуждать. Да, если вы собираетесь отображать его, когда (например) отображает Responses, и пользователи понимают UserName. Нет, если это 30 байт, а также есть 4 байт UserId. Идея состоит в том, чтобы сделать эти выборы сознательно, осознавая то, что вы отказываетесь, когда вы в конце концов решаете, что примерно 6-ти столбчатый 30-байтовый ключ слишком громоздкий, чтобы перейти к детям.

  • Вначале я сказал, что использую UserId как типичный Id Pk, потому что переносится/переносится на несколько дочерних таблиц.
  • Мы можем оставить, как это создано для более позднего. Но это чистый суррогатный ПК.

.
34. Нет проблем. Category уже есть. Я изменю Order на ListOrder.

.
35. Конечно. Основываясь на том, что я прочитал и услышал, я вполне доволен этим. Но я хотел бы больше назад и вперед, чтобы добиться некоторой уверенности, прежде чем писать код. В качестве альтернативы, рассмотрите его как опыт обучения и примите, что модель и код могут измениться позже. Вы хотите, чтобы я произвел Физическое сейчас? Если вы дадите мне все исправления, я опубликую следующую версию. Я ожидаю предпочтений в User. Кроме того, быстро выполните функции и убедитесь, что у вас есть все необходимые столбцы.

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

.
36. Объединяется. Вы просто присоединяетесь к fourтри столбца, а не один. SQL является громоздким с объединениями, и новый синтаксис, который должен был облегчить его, на самом деле является более громоздким. Мои кодеры никогда не записывают соединения: мы экономим время и опечатки. У меня есть proc, который дал две или более таблиц, будет генерировать код со всеми столбцами и объединениями. Я не знаю достаточно MySQL, чтобы преобразовать это для вас.

Обновлена ​​модель данных.
,

Комментарии re 08 Dec 10 20:49, Четвертая модель данных и ответы

.
Проверьте предыдущий раздел сразу, есть небольшие обновления.

IDEF1X: Ваша скорость в порядке.

Обратите внимание, что дочерний элемент всегда "наследует" родительский ПК, как FK (сплошная или ломаная линия), в противном случае между ними нет отношения. Используя эти столбцы, которые существуют в ребенке, чтобы сформировать дочерний PK, мы несли значение (и это разница между сплошным и сломанным). И поэтому нам не нужно искать независимый идентификатор для ребенка. Реляционная мощность в этом методе станет понятной позже, когда вы будете кодировать.

В разделе, о котором мы говорим, речь идет о Идентификаторы: естественный и неестественный; значимый против бессмысленного. Позже вы увидите, как мы можем использовать реляционные возможности движка, когда дочерний PK формируется из родительского ПК. (Разве ваша фамилия не совпадает с вашим отцом?)

Также важно понимать реляционные базы данных и их возможности. Это теряется, когда мы приближаемся к базе данных (например, с точки зрения ОО) и рассматриваем ее как место, чтобы сделать наши классы "постоянными". Поэтому мы попытаемся изучить и использовать Relational. Когда вы отправляетесь во Францию, становится сложно, и они ожидают, что они говорят по-американски, и используют ту же валюту; научитесь говорить по-французски десять слов, и они приветствуют вас с распростертыми объятиями, и у вас будет совсем другой опыт общения с местными жителями.

В любом случае, продолжите реализацию модели. Просто поймите, что мы, вероятно, в какой-то момент внесем изменения. Сохраните все ваши DDL. Сохраните все ваши тестовые данные в качестве операторов вставки или в виде резервного копирования таблицы или экспорта символов (не знаю, что MySQL может/не может сделать в этой области). .
37,1. Обработано, n:: n Отношение с Office и Category. Вы только "увидите" это, когда мы перейдем к физической модели.

37,2. Готово.

37.3 Готово.
.
38. Отлично. Короче. Обратите внимание, что они никогда не смогут иметь два Offices в одном и том же почтовом индексе. NUMERIC (5,0) хорош, но я думал, что США продвигаются к 7 цифрам. Неважно, вы можете понять это; это отличный ПК для Office. Теперь этот столбец, который был частью Address, вероятно, ZipCode, был повышен до более высокой цели без дублирования; так как мы переносим его в 5 дочерних таблиц, и мы хотим, чтобы имя PK было ясным, согласно ранее описанным соглашениям, мы будем называть его OfficeCode; OfficeZipCode может быть глупым.

Нам нужен уникальный индекс на Name, чтобы они не добавляли два Offices с тем же именем. Обратите внимание, что для объяснения это фактически логический ключ Office, заменяющий (StateCode, Town), и он остается таким.

Я все еще думаю, что вам может понадобиться StateCode и Town как быстрая ссылка (кроме сидения где-то в Address)

Обновлена ​​модель данных, пятая теперь доступна для обзора. Вы не указали свои предпочтения для ...Date vs ...Dtm. Я собираюсь с последним, так как это более spieific, также идентифицируя компонент времени. Легко изменить.

Этот ответ достиг максимальной длины. Продолжение в разделе "Часть II"

Ответ 2

Ключи к тому, чтобы эффективная база данных была упрощена. Основная цель реляционной базы данных - не повторять какую-либо информацию. Я взял ваш SQL-дамп и быстро разработал более простую версию, которая, насколько мне известно, нормализована. Я оставил некоторые поля, которые у вас были для cvs ect. Я удалил поля, которые проще было бы просто пересчитать, запросив db, когда информация понадобится, например, общее количество пользователей и рейтинг заданного сообщения. Я также удалил ваши bb_replies, поскольку вы можете выполнить тот же результат, ссылаясь на родительский пост. Я немного переименовал таблицы в то, что имело для меня смысл, вы можете использовать схему, которая вам нравится. Я нахожу, что использование простых терминов упрощает понимание того, как данные относятся друг к другу.

Я должен признать, что я согласен с некоторыми комментариями выше, есть много BBs, которые работают отлично, и у вас будет вся функциональность, которую вы ищете. И вам повезло, что я в настроении чтения сегодня вечером, это был длинный вопрос. Упрощение является ключевым во всем:)

alt text

SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @[email protected]@SQL_MODE, SQL_MODE='TRADITIONAL';


-- -----------------------------------------------------
-- Table `users`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `users` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `username` VARCHAR(45) NULL ,
  `password` VARCHAR(100) NULL ,
  `email` VARCHAR(255) NULL ,
  `first_name` VARCHAR(100) NULL ,
  `last_name` VARCHAR(100) NULL ,
  `permission` INT NULL ,
  `created` DATETIME NULL ,
  `modified` DATETIME NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `categories`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `categories` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  `description` TEXT NULL ,
  `order` INT NULL ,
  `admin` INT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `locations`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `locations` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  `description` TEXT NULL ,
  `address` TEXT NULL ,
  `order` INT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `posts`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `posts` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `post_id` INT NOT NULL ,
  `user_id` INT NOT NULL ,
  `category_id` INT NOT NULL ,
  `location_id` INT NOT NULL ,
  `title` VARCHAR(45) NULL ,
  `content` TEXT NULL ,
  `created` DATETIME NULL ,
  `modified` DATETIME NULL ,
  PRIMARY KEY (`id`, `post_id`, `user_id`, `category_id`, `location_id`) ,
  INDEX `fk_posts_users` (`user_id` ASC) ,
  INDEX `fk_posts_posts1` (`post_id` ASC) ,
  INDEX `fk_posts_categories1` (`category_id` ASC) ,
  INDEX `fk_posts_locations1` (`location_id` ASC) ,
  CONSTRAINT `fk_posts_users`
    FOREIGN KEY (`user_id` )
    REFERENCES `users` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_posts1`
    FOREIGN KEY (`post_id` )
    REFERENCES `posts` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_categories1`
    FOREIGN KEY (`category_id` )
    REFERENCES `categories` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_locations1`
    FOREIGN KEY (`location_id` )
    REFERENCES `locations` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `likes`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `likes` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `user_id` INT NOT NULL ,
  `post_id` INT NOT NULL ,
  `like` TINYINT(1)  NULL ,
  PRIMARY KEY (`id`, `user_id`, `post_id`) ,
  INDEX `fk_posts_users_users1` (`user_id` ASC) ,
  INDEX `fk_posts_users_posts1` (`post_id` ASC) ,
  CONSTRAINT `fk_posts_users_users1`
    FOREIGN KEY (`user_id` )
    REFERENCES `users` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_posts_users_posts1`
    FOREIGN KEY (`post_id` )
    REFERENCES `posts` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `sort_options`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `sort_options` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `name` VARCHAR(45) NULL ,
  `description` TEXT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `preferences`
-- -----------------------------------------------------
CREATE  TABLE IF NOT EXISTS `preferences` (
  `id` INT NOT NULL AUTO_INCREMENT ,
  `user_id` INT NOT NULL ,
  `pagination` INT NULL ,
  `sort_option_id` INT NOT NULL ,
  `categories_csv` VARCHAR(45) NULL ,
  `locations_csv` VARCHAR(45) NULL ,
  PRIMARY KEY (`id`, `user_id`, `sort_option_id`) ,
  INDEX `fk_preferences_users1` (`user_id` ASC) ,
  INDEX `fk_preferences_sort_options1` (`sort_option_id` ASC) ,
  CONSTRAINT `fk_preferences_users1`
    FOREIGN KEY (`user_id` )
    REFERENCES `users` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_preferences_sort_options1`
    FOREIGN KEY (`sort_option_id` )
    REFERENCES `sort_options` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;



SET [email protected]_SQL_MODE;
SET [email protected]_FOREIGN_KEY_CHECKS;
SET [email protected]_UNIQUE_CHECKS;

Ответ 3

Подзапрос Сначала, тогда функция RANK()

Отдохни, сынок, мы доберемся! Ваша скорость прекрасна.

Подготовка

Во-первых, вам действительно нужно получить доступ к достойному набору руководств для вашего конкретного вкуса MySQL. Я нашел ▶ этот <◀. Как и раньше, вы должны выполнить свою собственную отладку, но теперь я предоставляю SQL, максимально приближенный к универсальному MySQL. Я подтвердил, что все, что мы собираемся делать, вполне возможно в этом вкусе MySQL (я не знаю, какой вкус/версия у вас есть, кроме ENGINE = MyISAM).

Subquery

Хорошо, начнем снова. Я написал ▶ серию SELECTS ◀, чтобы провести весь процесс. Пожалуйста, заполните все и полностью поймите, прежде чем перейти к следующему. Если у вас есть вопросы, остановите и отправьте вопрос.

Код написан и протестирован в Sybase; затем понизился для MySQL (от просмотра Интернета, например, указанного выше сайта), и проверял как можно больше в этом состоянии.

Первый бит создает и загружает три таблицы для использования.

  • Первый SELECT - это прямое объединение трех таблиц, без подзапроса. Вам нужно заставить это работать; то есть понять, что есть, исправить любые проблемы синтаксиса; выяснить различия между SQL я предоставляю и SQL работает на вашем сервере. И привыкнуть к этим изменениям. Мы не можем продолжать останавливаться на этом.

  • Второй SELECT производит точно такой же набор результатов. Он вводит концепцию подзапроса, который используется для заполнения одного столбца.

Управляйте этой шиной. Ответьте, когда вы закончите, или если у вас проблемы.

Ответы на ваши комментарии от 03 дек. 10 17:51

  • Прямой Присоединиться Я никогда раньше не видел такого способа объединения, я всегда использовал левое соединение, прямое соединение или внутреннее соединение. Итак, для этого первого запроса мы просто присоединяемся к двум таблицам ученика и курса с таблицей учеников, сидящей посередине как ассоциативная таблица. Результаты повторяются, как ожидалось, потому что один студент может быть более одного курса, и у них будет результат для этого курса.

Да.

То (x = y в предложении WHERE) является традиционным способом идентификации объединений, это гораздо более ясно; синтаксис LEFT/RIGHT/INNER/OUTER JOIN является "новым" способом. Гораздо более громоздкий AFAIC, но учение актуально, потому что оно имеет фундаментальное значение для того, что приходит позже. Не стесняйтесь преобразовывать в последний синтаксис и обратно, для понимания.

Повторяется? Это не то, что означают повторы или дубликаты. Все строки являются дискретными, истинными строками в CS. Вы должны получать те же 15 строк в каждом отчете (по мере того, как мы продвигаемся).

(ps, когда я создаю таблицы, используя предоставленные вами запросы, имена преобразуются во все строчные буквы, тогда как имена столбцов все еще могут быть верблюжьим футляром.)

MySQL очень странный. (Кажется, что мы делаем соглашения об именах для нас!)

.
2. Простой скалярный запрос
Несколько вопросов с запросом. Вы используете псевдоним (в скалярном подзапросе) до того, как вы определили, что это такое (StudentCourse sc) Я полагаю, что я всегда неправильно предполагал, что вы должны сказать, чтобы определить псевдоним, прежде чем использовать его.

Вы думаете о процедуре. SQL - это язык, ориентированный на набор, для управления реляционными наборами данных.

Весь запрос оценивается и оптимизируется за один проход. Нет "до" или "после". Я определяю его в той же серии SQL, что и я.

Я не совсем понимаю использование псевдонима "in-ner" в скалярном подзапросе, это означает, что вы хотите, чтобы он проверял каждую строку отдельно (не уверен, как это объяснить), а не на таблице широкоформатная проверка? Т.е. когда вы делаете эту проверку, сделайте ее локальной для конкретной строки, на которой вы находитесь? (ужасное объяснение извините).

Для понимания/отладки сначала оцените подзапрос (содержимое скобок). Понимайте это полностью. Обратите внимание на использование "sc" и сохраните его в шляпе.

  • in_ner и sc являются ALIASES, то есть обрабатывает имя таблицы, которое расположено рядом с предложением FROM; что мы используем в другом месте кода для удобства
  • in_ner - описательное имя для таблицы, указанной во Внутреннем запросе, Подзапрос
  • sc - это описательное имя для таблицы, на которую делается ссылка в Outer Query, которая является только Outer, поскольку она содержит внутренний запрос, иначе это будет плоский запрос
  • мы могли бы просто использовать fred и sally
  • Псевдонимы, такие как in_ner и out_er, имеют смысл, когда одна и та же таблица ссылается как на Внутренние, так и на Внешние запросы.
  • Обратите внимание на соединение между Внутренним запросом и внешним тестом WHERE in_ner.CourseId = sc.CourseId
  • У меня есть связанная таблица, на которую ссылается запрос in_ner на таблицу sc, указанную в запросе Out_er
  • Такой подзапрос называется корреляционным подзапросом

Посмотрите, можете ли вы визуализировать внешний запрос (набор результатов) как сетку, электронную таблицу, 15 строк по 4 столбца.

  • Удостоверьтесь, что вы понимаете, что Outer query, "простой", как есть. Обратите внимание, что это то же самое, что (1. Straight Join), с другим методом заполнения одного столбца.

Как я понимаю, скалярный подзапрос запрашивает имя, где курс в курсе и студенческом тесте один и тот же. (довольно прямолинейно) и является альтернативой высказыванию, что в том, где

Да, точно.

И обратите внимание, что мы следуем только с Course.Name, которое является 1:: 1, от StudentCourse до Course, CourseId. Обратите особое внимание на предложение WHERE в (1), которое мы заменяем в (2); в (1) применяется ко всем строкам.

Но, потому что мы хватаем одну дату; одна ячейка; один элемент для определенной строки/столбца; не все строки; не все столбцы, это называется Scalaр.

Мы получаем его с помощью подзапроса, который должен быть ограничен определенной строкой. Поэтому нам нужно связать строку из внешнего запроса с строкой во внутреннем запросе.

  • поэтому требуется Корреляция между Внутренним Подзапросом и Внешним (конкретная строка).

  • И если бы у нас не было такой идентификации конкретной строки, мы бы загрузили мусор в Scalar или вернули таблицу (а не значение Scalar), и запрос не получится.

    • Попробуйте, возьмите WHERE CourseId = sc.CourseId вне
    • Чтобы вы знали, что такое сообщение об ошибке, так что, когда это произойдет в будущем, вы узнаете: "Ага, я возвращаю таблицу, а не скаляр, я что-то пропускаю в своем внутреннем WHERE; я не определяю конкретную коррелированную строку".
      ,
  • он не совсем "просит имя, где курс в курсе и студенческой школе одинаковый"; он получает значение Course.Name для определенного StudentCourse.CourseId, который идентифицируется извне, независимо от того, какая строка sc есть.

с differnece, что вы можете сделать эту проверку подряд за строкой перед тем, как это сделать.

вы думаете о процедуре; нет "строк за строкой"; dbms установлен -ориентирован; результат набор, который вы создаете, - это set. Переформулируйте вопрос: установить терминологию.

Я использовал Course вместо или in-ner, в чем смысл использования псевдонима в этом случае, просто показать, что можно использовать псевдонимы?

Да. И чтобы выделить вопросы. И чтобы дифференцировать Внутренний запрос от внешнего запроса. Во внутреннем запросе "внутренний" псевдоним или любой псевдоним не требуются. Требуется только псевдоним, относящийся к внешнему запросу.

Что-то, что я не понимаю здесь, это то, что, когда я пытаюсь это сделать, "course.Name", он говорит неизвестное имя Course.Name в списке полей. так я всегда определял, что я имею в виду имя в таблице курса, а не какую-то другую таблицу. Что произойдет, если у меня есть две таблицы с столбцом имен?

Совершенно верно. Если бы это было неоднозначно, тогда вы бы имели, чтобы указать имя таблицы или псевдоним; где он не двусмыслен, он не востребован, но приятен для документального, ясности, целей. Вы должны понять, почему MySQL не принимает его. Сумасшествие смешанного случая/нижнего регистра?

Я тоже никогда не видел этот порядок по синтаксису, я вижу, что 1 и 4 означают номера столбцов, но зачем беспокоить передачу двух столбцов?

А? Поскольку я хочу, чтобы результирующий набор упорядочивался по Course.Name в порядке возрастания и внутри этого, по StudentCourse.Mark в порядке убывания.

Если бы я не указал порядок, MySql создаст результирующий набор в любом порядке, который он получит от StudentCourse (хронологический? по индексу?). Независимо от этого стандартного порядка, найдите это, вы должны это знать и, таким образом, избегать ORDER BY, когда это не нужно.

  • Возьмите ORDER BY и играйте с ним.

  • Попробуйте ORDER BY 4 DESC, 1

Это не "передача", я говорю, что делать с моим результирующим набором, в одной команде SQL. Единственное, что вы делаете, это ваше приложение (PHP?) И MySQL.

2,1. Хорошо, когда вы закончили с (2) и полностью счастливы, что понимаете это, выполните это упражнение.

SELECT  (SELECT Name
            FROM  Course
            WHERE CourseId = sc.CourseId
            ) AS CourseName,
        () AS FirstName,
        () AS LastName,
        Mark
    FROM StudentCourse sc
    ORDER BY 1, 4 DESC
  • Создайте тот же формат сетки, мы хотим, чтобы точно такой же результат был задан как (1) и (2).

  • Заполните две пары пустых скобок соответствующим подзапросом; то есть. напишите подзапрос, чтобы заполнить столбец FirstName, а другой - заполнить столбец LastName

Ответы на ваши комментарии re Третья модель данных

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

Коррелированный скалярный подзапрос говорит, что для каждого идентификатора курса нам нужна отметка highst, а не самая высокая отметка для всех курсов. Здесь коррелированный аспект этого подзапроса вступает в игру, потому что мы связываем внешний запрос с внутренним запросом для этой конкретной строки. [ Да!] Способ, которым я в настоящее время визуализирую [Что это, используйте визуальную часть вашего разума, а не серийную часть] it заключается в том, что внешний запрос выполняется через таблицы, объединяющие набор результатов table, и каждый раз, когда он создает строку, он запускает скалярный подзапрос и выбирает [одно значение для заполнения ячейки; здесь это] наивысшая отметка, где matchId совпадает, поэтому, когда он находится в строке, где идентификатор курса равен 66, тогда скалярный подзапрос ищет только максимальную метку, где courseId равен 66.

Я едва мог бы сказать это лучше себя.

Нет такой вещи, как "таблица результатов".

Добавьте еще один окончательный элемент.

  • Внешний запрос определяет набор результатов.

    • Подзапрос не зависит от этого; он просто коррелирован или индексирован.

Итак, у вас есть этот SQL-рабочий, верно?

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

Теперь оставьте этот двухмерный результат в одиночку на минуту и ​​визуализируйте еще один слой поверх него. Это параллельный слой, где вы пишете свой код подзапроса.

Если вам трудно получить подзапрос для работы, вернитесь к этому, ваш способ визуализации, один набор результатов и другой слой для подзапроса, в который заливается ведро скаляров, чтобы заполнить столбец. Он устраняет все известные ошибки кодирования подзапросов; удаляет использование GROUP BY, DISTINCT и всех этих способностей, создающих длинную злую змею, чтобы вписаться в банку с джемом.
.
Еще три маленьких шага, прежде чем вы перейдете к (4).

2.2 Перечитайте мой ответ (2) выше, вплоть до этой точки. Нет скимминга. Это происходит потому, что, когда вы учите своему разуму что-то новое и другое, вам нужно снова его понять. Это официально признанная техника.

Ответы на комментарии от 08 дек. 10 20:49

2,3. Напишите этот запрос (3) без использования подзапросов и убедитесь, что вы проверяете результаты. Если вы поймете, что смеетесь, когда пишете код, это хороший знак. Пока вы производите правильный набор результатов, вы проходите, но пытаетесь написать наиболее эффективный код (наименьшее количество COUNTS и GROUP BY и т.д.). Сделайте это только в том случае, если вы хотите запускать круги вокруг своих сверстников, чтобы иметь возможность ответить на любой вопрос "как мне кодировать..." в вашей базе данных.

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

Да. Абсолютно. Вы пошли вперед. Теперь идите назад, не спотыкаясь. Это действительно поможет вашему пониманию ходьбы вперед, когда лучше использовать подзапрос и соединение. Введите запрос с помощью GROUP BY и COUNT. Наименьшее. Не смейтесь.

2,4. Напишите подзапрос (3) в вашей базе данных, чтобы создать список Bulletins, внешний запрос должен быть FROM bbs; с числом likes и числом dislikes. Так trunacte таблицы и делать 10 или 12 значащих INSERTS, fibe минут, большое дело.

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

Хорошо, это прекрасно. Теперь мы получаем немного реляционной силы в вашем шпинате.

Теперь перейдите и посмотрите на вопрос и ответ; убедитесь, что вы сравниваете код. Вы прошли долгий путь всего за несколько дней.

Когда вы закончите (2.3), снова прочитайте запрос (2.4), чтобы обновить себя и перейдите на (4).

Если вы застряли, замените слово "Ранг" на "CountOfStudsWithHigherMark" и дайте ему еще один шаг.

Ответы на комментарии от 11 декабря 10 13:14

2.3 У меня возникла проблема с записью этого запроса без скалярного подзапроса. Скалярные подзапросы всегда были более логичным для меня, даже до того, как я знал, как их выполнять. Вот почему я сказал: "Я думаю, проблема, с которой я столкнулся, заключается в том, как вы относитесь к user-id = x в этой конкретной строке, а не ко всей строке" в предыдущем вопросе. Ответ был связан с корреляцией скалярного подзапроса с основным запросом и псевдонимом.

Упражнение (2.3) предназначено для вас:

  • действительно понять неверность жирного запроса с помощью GROUP BY (в реляционной базе данных с использованием реляционного движка с комплексной обработкой) в сравнении с правильностью, элегантностью и скоростью коррелированного подзапросы. Вы достигли этого. Это поставит вас выше ваших сверстников с точки зрения способности SQL-кодирования.

  • иметь возможность идентифицировать, когда условие fat WHERE и соответствующий корреляционный подзапрос. Я не уверен, но похоже, что вы это достигли.

  • иметь возможность исправлять и отлаживать эту проблему при сохранении кода, написанного другими, и уметь обучать их различию. Похоже, у вас хорошая визуальная, реляционная способность; которая была повторно освещена учением; и теперь вы не можете вернуться к более низким методам. То есть вы можете понять и исправить неправильный код SQL, но вы не можете сообщить об этом другим.

Пока вы понимаете эти различия и принимаете это, я рад отказаться (2.3) и двигаться дальше.

Снова прочтите запрос (2.4), обновите себя и перейдите на (4).

Если вы застряли, замените слово "Ранг" на "NumStudentsWithHigherMark" и дайте ему еще один шаг.


Не читайте дальше. Ниже приведен "старый код"

Здесь ▶ Quick Tutorial ◀ для оператора RANK() (как это обычно известно). Это не ANSI SQL; это расширение Oracle и MS. Однако это не требуется, если вы понимаете подзапросы, поэтому Sybase его не имеет. Я сомневаюсь, что у MySQL это есть, поэтому вам нужно обдумать это. Понимание Скалярных подзапросов является предварительным условием. Sybase синтаксис, так что ударяйте ваши полуколоны и т.д. Не стесняйтесь задавать конкретные вопросы.

Я никогда не видел такого подхода к записи Rank = (SELECT.... Это то же самое, что (SELECT...) как Rank?

Да, () AS Rank вместо Rank = () являются как законными SQL; MySQL может не понравиться последняя форма. Скобки, содержащие Подзапрос, конечно. Обратите внимание, что Rank - это имя производного столбца.

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

Попробуйте это (я поставляю ANSI Standard SQL, у меня нет MySQL, вам нужно будет синтаксически исправить его для MySQL, я не исправляю проблемы с синтаксисом, это ваша работа):

SELECT  COUNT(*)+1 AS Id_iot  -- not you, everyone who uses them blindly
        (SELECT title in_ner FROM bb_locations WHERE out_er.bb_locations_id = in_ner.id) AS Location,
        title AS Bulletin,
        created_date AS Date
    FROM bbs out_er
  • in_ner и out_er являются ALIASES, то есть обрабатывает имя таблицы, которое расположено рядом с предложением FROM; что мы используем в другом месте кода для удобства
  • in_ner - описательное имя для таблицы, указанной во Внутреннем запросе, Подзапрос
  • out_er - это описательное имя для таблицы, на которую делается ссылка в Outer Query, которая является только Outer, потому что у нее есть внутренний запрос, иначе это будет плоский запрос
  • мы могли бы просто использовать fred и sally
  • обратите внимание на соединение
  • У меня есть связанная таблица, на которую ссылается запрос in_ner в таблицу, указанную в out_er query
  • Такой подзапрос называется корреляционным подзапросом
  • Это просто пример, простой, чтобы вы могли изучать подзапросы; специально выбранный для обеспечения того же результата, что и тот, который вы знакомы с производством, используя прямые соединения (bbs и bb_locations в предложении FROM, соединяющиеся с помощью предложения WHERE или JOIN).
  • Поскольку он создает одно значение, он называется Скалярным подзапросом (те, которые производят строки, являются подзапросами в таблице и не могут использоваться таким образом, чтобы загрузить одно значение в каждую строку)
  • Нет никаких предположений о том, что кто-то должен "использовать подзапросы вместо Joins". Абсурд. Подзапросы имеют свое место, и у них есть свои. Неправильное поведение - это другое дело.

Теперь прогоните эту шину. И не говорите мне о RANK, пока вы не сможете управлять этим автобусом вокруг каждого угла в вашем районе базы данных, не убивая всех детей.

Я не понимаю внутреннего и внешнего, когда я говорю им, я получаю INNER JOIN, что они называются, поэтому я могу продолжить исследование

Псевдонимы. См. Выше.

Когда я запускаю этот оператор select, я получаю эту ошибку. У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с WHERE inner.Mark >= external.Mark) FROM studentmark external ORDER B 'в строке 5

  • сначала, по причинам, описанным выше, я не могу написать синтаксис MySQL, а отладка - это ваша работа.
  • Во-вторых, я понимаю, что вы не можете отлаживать то, что вы не можете понять, поэтому отбросьте его на данный момент (это связано с RANK), и, изучив SQL-код SQL, все это будет разрешено
  • В-третьих, позвольте мне заверить вас, что он работает на любом стандартном SQL-сервере. Он используется примерно в 10 курсах в год, поэтому сотни участников в год. Я просто запустил его снова на Sybase, просто чтобы проверить.
  • Первое, что я хотел бы предложить, это то, что оптимизатор MySQL сосет мертвых медведей; он не понимает контекста, inner и outer, вероятно, рассматриваются как зарезервированные слова. Поэтому измените это в соответствии с приведенным выше кодом.

Ответ 4

Часть II

Продолжение части I, из-за того, что этот ответ достигает максимальной длины.

Пересмотрено 14 января 11 - 05:40 PST

Комментарии re 11 Dec 10 13:14, Пятая модель данных и ответы

а. IDEF1X инструмент для создания/диаграмм.
Я не знаю никаких бесплатных программ. Сообщается, что инструмент проектирования MySQL часто падает. Если вы довольны моими диаграммами, я рад работать с вами на время, пока окончательная модель не будет решена; то есть. Я предоставляю модель данных, и вы можете пропустить эту задачу. Для текущей работы да, вам нужен инструмент построения диаграмм, возможно, не инструмент проектирования базы данных. См. Мои комментарии в конце p2 в документе Notation.
.
29. Вы четко разбираетесь в ПК и FK в каждой таблице, в соответствии с цветными вкладками в пятой модели данных; я могу удалить вкладки сейчас?
.
38. Закрыто.
.
39. Все столбцы Dtm будут типами данных MySQL DATETIME. Переменные, которые вы используете для этих столбцов, должны быть одинаковыми. TimeStamp имеет другое значение. Использование правильных типов данных - это первый (большой) шаг к обеспечению того, что данные коректированы, и никакие незаконные значения не могут войти в db. То есть допустимые даты и время будут разрешены. Кроме того, вы можете опросить любой элемент даты или времени (например, месяц или день). Проверьте этот документ.
.
40. Нет проблем. Вместо того, чтобы иметь только одну категорию с жесткой кодировкой, как насчет (например, обработки вашего разрешения), мы реализуем Category.IsRestricted, а затем Permission 5 становится Post Restricted Bulletins.
.
41. Сделано.

Вы должны подумать о том, чтобы сделать то же самое для Category и User. Вы хотите удалить их, установив индикатор, не удаляя запись (и все Bulletins, Responses, Replies и т.д.) Из базы данных. Он должен быть сохранен для исторических целей, но вам нужно запретить Пользователю входить в систему и делать что-либо. Я включил это в DM.

Для таких имен столбцов и булевых в целом лично я предпочитаю идентифицировать случай меньшинства или исключения, как в IsObsolete.

20,2. Готово. Именование таблиц и столбцов теперь перешло в формат InnoDB.
.
Ответы подзапроса в ответе Subquery.

Комментарии 13 Дек 10 13:14 EST и ответы

.
41. См. (41) и следующий параграф выше.
.
42. Я имел в виду: достаточно Title или Description; нам не нужны оба.
.
43,1. Реализация модели данных. Преуспевать. Вот почему я дал тебе вчера Физику. .
43,2. Дизайн/Рисование. Преуспевать. Я уже прокомментировал (а) выше.

Модель данных

Шестой модель данных, содержащий все изменения, указанные выше.

Физическое означает намного больше деталей, необходимых для реализации/кодирования: Типы данных; n:: n Связи, реализуемые как ассоциативные таблицы; и т.д. Вы в значительной степени готовы реализовать модель данных, а это значит, что вам нужно физическое. И вы уже определили Ассоциативные таблицы. Поэтому я позволил вам предоставить вам физический DM, хотя вы сказали, что не спешите.

  • Обратите внимание, что Домены (User Defined Datatyptes) всегда должны использоваться в базе данных, как для DDL; переменные $, которые вы используете. И частный домен для каждого основного ключа. Но это невозможно в MySQL, поэтому Datatypes являются грубыми, к сожалению.

  • Столбцы с фиксированной длиной намного быстрее, чем переменная длина; Я не предоставляю (советую) длину Вар. Вы можете реализовать то, что вам нравится.

  • Вы уверены, что вам нужны как Category.Title , так и Description? Я думаю, что нет, но я оставил его, пока не подтвержу.

  • Наслаждайтесь маленькими кнопками синего стекла и навигацией от сложенных сущностей.

Снова прочитайте документ нотификации IDEF1X, я расширил его на прошлой неделе.

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

Комментарии 28 дек 10 10:34 и ответ

Я начал внедрять модель данных. Я предполагаю, что 6-я модель данных является физической моделью, поскольку она содержит ассоциативные таблицы.

Да, я предоставил это и Datatypes, потому что вы сказали, что готовы к реализации.

Есть еще несколько незначительных предметов. Может быть, хорошо провести свой вопрос; все три моих ответа и проверить. Category.Title и Description, например.

Я поставлю дамп базы данных, как только закончим.

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

Затем я выложу список всех запросов, которые мне нужно запустить в базе данных, и начните их писать.

Очень хорошая идея, принять структурированный и планируемый подход к работе.

Реализация физической модели

(39) С mysql я не могу назначить более одного первичного ключа, поэтому я просто собираюсь сделать их уникальными, а не null, как вы предлагаете в документации. Считаете ли вы, что было бы неплохо также их индексировать?

Не уверен, что вы имеете в виду, что такое "они"?:

  • у вас никогда не может быть более одного основного ключа на столе; Альтернативные ключи уникальны, один из них "первичный"; который переносится как FK в дочерние таблицы.
  • с InnoDB (что вы сказали, что получите), вы можете определить ограничения PRIMARY KEY (что эквивалентно UNIQUE, NOT NULL)
  • с MyISAM (что у вас есть), вам нужен индекс, UNIQUE, NOT NULL для основного ключа (над линией в модели)
  • для InnoDB или MyISAM, каждый альтернативный ключ (AKx[.y] в модели) должен быть определен как дополнительный индекс, UNIQUE, NOT NULL.

Комментарии 07 янв. 11 14:08 и ответ

(40) Не могли бы вы объяснить, почему category.CategoryCode является char из 4 символов. Почему бы просто не использовать номер, например, для пользователя?

40,1. Идея состоит в том, чтобы использовать хорошие натуральные Идентификаторы. Номера не имеют смысла для пользователей. Если бы у нас не было большого количества Пользователей, а Пользовательский отток, я бы не использовал там номер. A CHAR (2) или (3) или (4) позволяет им выбирать осмысленный короткий код для длинной категории. Описание и достаточно мало для переноса в качестве внешнего ключа в user_category и bulletin.

Для разработчика при тестировании и отладке этот короткий код в списке say bulletins будет очень удобен.

(40) Я не совсем понимаю разрешения для категории и местоположения. Допустим, что я хочу, чтобы все пользователи могли отправлять сообщения в категорию "Путешествия". Могу ли я установить разрешение этой категории на 4? Почему нам нужно bool IsRestricted, когда мы даем разрешение на категорию и местоположение?

40,2. Я не изменил концепцию или сущность разрешения; это была ваша идея, и она остается такой же, как вы объяснили мне.

(Все, что я сделал, это реализовать permission как таблицу.)

40,3. См. (13) и (40) первоначальный обмен. Category.IsRestricted определяет ограниченные категории; существуют две категории categories, Ограниченные и неограниченные. Пользователям нужен permission из 5 для публикации бюллетеней re Ограниченные категории и 4 для публикации бюллетеней re Неограниченные категории.

40,4. Но ты, сын, вводишь изменения или расширения. например. сопоставьте permission User с permission Category, таким образом, предоставляя гораздо больше двух категорий categories? Пожалуйста, не надо. Это означало бы, что permission означает одну вещь re Category и другую вещь в остальной части системы. Или если вы это сделаете, тогда нам нужно сначала решить нужную потребность, а затем реализовать ее как изменение.

40,5. Местоположение (сейчас office) точно такое же для этого бита (40.2) и (40.3). Если вы имеете в виду текст внизу, это моя небольшая ошибка, исправит его.

40,6. Согласно (14), office дополнительно имеет один AdministratorId (UserId). Показан на модели как (permitted) user.

40,7. Но это вызывает проблему: кто может управлять categories? Прямо сейчас кто-то с permission 5 или выше, это совсем другое. Я думаю, что нам нужно что-то явное, permission 6 = Категория администратора.

Другие

  • Обработал ваш DDL и вернулся.

  • Обновлена ​​модель данных. Исправлено количество небольших пояснений и две незначительные ошибки.

Комментарии 08 янв. 11 14:08 и ответ

(Я думаю, что это было 09 января, но не 08 января... Я проверял наличие обновлений.)

(40) Я не совсем понимаю разрешения для категории и местоположения. Я ничего не изменил. Не обращайте внимания на содержание предыдущего вопроса, объясняя, какое разрешение будет установлено, чтобы пользователи могли публиковать сообщения в категории "Путешествия". В моей реализации у меня просто был столбец разрешений. Если у данного пользователя было требуемое разрешение или больше, то они могли отправлять сообщения в категорию, это то, как работает новая система?

Да. Без изменений. category.permission не имеет к этому никакого отношения. Им нужно user.permission 4 для неограниченного categories.

Если Category.IsRestricted, они нуждаются в user.permission 5.

В отдельности пользователю требуется user.permission любого category.permission, чтобы управлять Category. Не используйте значения менее 4.

(41) Запрос Удалить бюллетень и все связанные с ним ответы и оценки.

Я не ожидал этого, уверены ли вы, что им не нужно хранить все прошлые бюллетени для целей истории или аудита?

В любом случае, разрешите это с учетом того, что удаление бюллетеней разрешено...

Я даже не знаю, с чего начать. Раньше я присоединился, присоединил бы таблицу бюллетеня с таблицей ответов и таблицей ответов с таблицей оценки ответа и таблицей рейтинга бюллетеня, где идентификатор бюллетеня = x и удалил их. Но теперь любой конкретный бюллетень идентифицируется тремя столбцами: OfficeCode, Publisherer и BulletinDtm. Которые переносятся в дочерние таблицы как внешние ключи. Для начала, как я могу указать, какой бюллетень нужно удалить в моем php? Обычно у меня бы была ссылка вроде index.php?action=delete&bulletin-id=5. Теперь мне нужно иметь ссылку, которая index.php?action=delete&OfficeCode=20001&IssuerId=34&BulletinDtm=14:02... Я действительно не знаю, как это сделать?

а. Я не могу вам помочь, я эксперт по базам данных и SQL, а не специалист по php или MyISAM. Вам нужно будет опубликовать это как новый вопрос о SO или платах MySQL.

б. Насколько я читал эту тему, я не знаю синтаксиса, но да, это можно сделать, это нормально. Я проверил, прежде чем рекомендовать вам составные клавиши. Скорректированный DDL преуспел, и индексы подтверждены, правильно?

с. Проблема заключается просто в синтаксисе, требуемом для составных или составных ключей; и работает с index.php. Что-то вроде:

index.php? action=delete & OfficeCode=x and IssuerId=y and BulletinDtm=z

д. Почему вы не можете использовать mysql_query вместо index.php и, следовательно, использовать полный SQL? Насколько я понимаю, он работает с MyISAM. Затем вы можете использовать:

`$sql = "DELETE $table WHERE OfficeCode=$OfficeCode AND IssuerId=$IssuerId AND BulletinDtm=$BulletinDtm";`

е. Сначала удалите response_rating; затем response; затем bulletin_rating; то bulletin. Когда они переключаются на InnoDB, у них будет меньше изменений.

ф. Самое главное, вам придется найти их для определения основы, на которой можно удалить бюллетень. Любой и все бюллетени не должны удаляться. Что-то вроде "никакой активности в течение одного года" или "закрыто" (что означает добавленный столбец) и т.д.

Комментарии 10 янв. 11 14:08 EST и ответ

(41.10-Jan-11) Нет проблем, метод в порядке, и у меня есть подробные связанные вопросы, которые требуют адреса в соответствии с (41. *) выше. (41.f) все еще нужен ответ... кроме разрешений, существует ли база для удаления бюллетеней?

Комментарии 10 янв. 11 13:48 pst и ответ

Редактирование SO. Не волнуйся, это не ты. Сайт плохого технического качества. Редактирование является безнадежным (и поверьте мне, я пытался работать с ним и вокруг него, чтобы сделать мои ответы похожими, как будто я хочу, чтобы они появились). Он не может обрабатывать отступы или более одного уровня нумерации правильно.

Удалить базу. Хорошо, у вас есть действующая основа. И пользователи, которые писали responses, не возражали бы, если бы они были удалены без запроса?

(41) То, что вы ищете, является "каскадным удалением" в стандартном SQL, которое определено в предложении Foreign Key (которого у вас нет в MyISAM). Каждый глагол INSERT/UPDATE/DELETE применяется только к одной таблице и может влиять на другие таблицы по ССЫЛКЕ.

Для нестандартных SQL-адресов у вас есть метод DELETE multiple_table (нестандартный синтаксис).

Во-первых, это очень важно понять прежде всего. Предложения FROM и WHERE (или JOIN) в команде DELETE являются отдельными для самого DELETE; они на самом деле являются SELECT. Идея такова: DELETE table_one (SELECT FROM table_one, table_two WHERE join_conditions).

Таким образом:

  • укажите четыре таблицы в DELETE (target)
  • укажите четыре таблицы в FROM (как вы их найдете через SELECT)
  • убедитесь, что у вас есть правильные (полные) предложения JOIN для четырех таблиц; который вы можете проверить с помощью SELECT
    • что означает, ПРИСОЕДИНЯЙТЕСЬ на OfficeCode, Эмитент, BulletinDtm (bulletin PK, влияющий на дочерние таблицы)
    • использовать соединения NATURAL или INNER, не левые соединения (быть явным, не смешивать их, как правило)
  • убедитесь, что WHERE идентифицирует конкретный bulletin составной первичный ключ для удаленных.

Здесь ссылка на Синтаксис DELETE и JOIN синтаксис.

Комментарии 12 янв. 11 21:48 и ответ

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

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

  • Я просто написал этот код для другого вопроса. Это единственная команда SELECT. Трехколоночный PK раз четыре подзапроса. Я не понимаю необходимости избегать долгого (требуемого, опять же, из-за громоздких) SQL-команд. И я даже не использовал синтаксис JOIN. Принял меня все десять минут, чтобы написать, плюс пять минут, чтобы проверить. Что именно, это большая сделка?

с. Вы не забыли силу реляционных ключей, которые вы узнали несколько недель назад, не так ли? Например. способность захватывать бюллетень от рейтинга, без с присоединиться к рейтингу. Если вы уступите своим желаниям с одним столбцом, вы потеряете все это. SQL является громоздким. Но это все, что у нас есть. Смирись с этим. Не-SQLs пытаются "сделать жизнь легкой", но на самом деле представляют всевозможные ненужные и предотвращаемые осложнения. Пример.

Комментарии от 13 января 2011 21:18 PST и Response

Удаление. Три аромата. Отлично. Надеемся, что вы будете иметь значения данных в $переменных, поэтому не будет такой формы повторения. Для тестирования это нормально.

  • Удалить x Четыре таблицы. (а не "Индивидуальное удаление записей", что совсем другое: каждое удаление, кроме последнего, может содержать сотни строк). Я верю, что вырезать-вставить потребовалось несколько секунд. Вы должны быть осторожны, забыв изменить имена таблиц.

  • Команда одиночного удаления. $переменных для первого триплета. Вы можете использовать имена столбцов во всех, кроме первого триплета.

  • Итак, после тестирования вы преобразуете SELECT в DELETE. Левые соединения. Требуется для одиночного удаления, но не иначе. То, что совпадает с (2) с WHERE, заменено JOIN >

Я уже рекомендовал (1), но у вас больше шансов пойти (3).

Следующий запрос?

Холодный день. Приятные середины двадцатых годов. Полностью аномальная погода, по всей Планете. Обычно здесь около тридцати, не так много недель. Квинсленд затоплен после 9 лет наихудшей засухи. Держите тепло и сухо. Возьмите напрокат автомобиль и пройдите достаточно далеко, чтобы никто не услышал выстрел. До н.э. не является Пенсильвания; они делают это все время; олени в миллионах.

Приветствия.

Ответ 5

Не бойтесь присоединяться. Если бы я был вами, я бы сократил всю логику БД, которую вам нужно написать и использовать ORM, например Doctrine или Propel, это упростит процесс проектирования и поддержки, включая все те объединения, которые вы пытаетесь избежать.