Як зробити простіші запити складних SQL запитів? [зачинено]


42

Мені дуже важко писати складні запити SQL, що включають об'єднання в безліч (принаймні 3-4) таблиць і включають кілька вкладених умов. Запитання, які мені просять написати, легко описуються кількома реченнями, але для завершення може знадобитися обманлива кількість коду. Я часто зустрічаюсь із тимчасовими поглядами, щоб писати ці запити, які здаються трохи прихабними. Які поради ви можете надати, щоб полегшити ці складні запити? Більш конкретно, як я розбиваю ці запити на кроки, які мені потрібно використовувати, щоб фактично написати SQL-код?

Зауважте, що я SQL, який мені просять написати, є частиною домашніх завдань для курсу бази даних, тому я не хочу програмного забезпечення, яке буде робити мені роботу. Я хочу насправді зрозуміти код, який я пишу.

Більше технічних деталей:

  • База даних розміщується на сервері PostgreSQL, який працює на локальній машині.
  • Бази даних дуже малі: не більше семи таблиць, а найбільша таблиця має менше 50 рядків.
  • SQL-запити передаються без змін на сервер, через LibreOffice Base.

Тимчасові представлення насправді є досить корисними, оскільки ви можете робити такі таблиці (як явні складні індекси), що дуже важко натякнути на аналізатор SQL.

Особисто мені легше обдурити, використовуючи графічний інтерфейс (наприклад, LibreOffice Base "Створити запит у дизайні перегляду" або Office Access "Створити"> "Дизайн запитів"), а потім переглянути SQL, який він створює. Іноді доводиться змінювати SQL, наданий дизайнером графічного інтерфейсу, але це дає хорошу вихідну точку
kurdtpage

Відповіді:


49

Я основую більшість цього на тому, що я просто намагаюся отримати "правильну" відповідь, тож ви можете виявити, що є деякі проблеми з продуктивністю. Немає сенсу прискорити неправильний запит.

Зрозумійте відносини таблиці - Більшість буде одним до багатьох. Знайте таблицю «багато». Визначте поля, необхідні для ваших приєднань.

Подумайте про сценарії приєднання Ліворуч - Виберіть усіх працівників та їх зарплату за останній місяць. Що робити, якщо вони не отримали зарплату минулого місяця?

Знайте набір результатів: 1) У таблицю введіть вручну принаймні один правильний запис для вашого запиту. 2) Напишіть запит у досить простій формі, щоб визначити, скільки записів потрібно повернути. Використовуйте обидва для тестування свого запиту, щоб переконатися, що приєднання до нової таблиці не змінить результат.

Розбийте свій запит на керовані частини - Вам не потрібно писати це все відразу. Складні запити іноді можуть бути просто набором простих запитів.

Остерігайтеся змішаних рівнів агрегації : Якщо вам потрібно вводити щомісячні, квартальні та річні значення в один набір результатів, вам потрібно буде їх обчислити окремо в запитах, згрупованих за різними значеннями.

Знайте, коли до UNION. Іноді простіше розбити підгрупи на власні оператори вибору. Якщо у вас є таблиця, змішана з менеджерами та іншими працівниками, і в кожному стовпчику ви повинні робити заяви про випадки, засновані на членстві в одній з цих груп, можливо, простіше написати запит менеджера та об'єднання до запиту працівника. Кожен би містив власну логіку. Очевидною необхідністю включати елементи з різних таблиць у різні рядки.

Складні / вкладені формули - намагайтеся послідовно відступати і не бійтеся використовувати кілька рядків. "СЛУЧАЙ, КОЛИ СЛУЧАЙ, КОЛИ СЛУЧАЙ КОЛИЙ" призведе до того, що ви будете ганяти Знайдіть час, щоб продумати це. Збережіть складні обчислення останніми. Спершу виберіть правильні записи. Потім ви атакуєте складні формули, знаючи, що працюєте з правильними значеннями. Перегляд значень, використаних у формулах, допоможе визначити області, де потрібно враховувати значення NULL та де обробляти помилку поділу на нуль.

Тестуйте часто, додаючи нові таблиці, щоб переконатися, що ви все-таки отримуєте бажаний результат і знаєте, який винуватець приєднання чи пропозиції.


1
Дійсно чудові речі. Я хочу переосмислити точки Джеффа щодо пошуку лівих приєднань та розділення складних запитів на більш дрібні, більш керовані, а потім їх поєднання. Я пишу великі запити на великих базах даних щодня, і ці дві речі, зокрема, постійно виникають. Завжди запускайте запити та підзапити, як тільки зможете, щоб переконатися, що ви отримуєте дані, які ви очікуєте бачити на кожному кроці.
CodexArcanum

@CodexArcanum - і коли ви запускаєте запити на великих даних, не завадить використовувати TOP;)
JeffO

Я погоджуюся з кожним твердженням вашої пропозиції
Алессандро Россі

28
  1. Відступ було б першим ділом, якщо ви цього ще не робите. Він не тільки корисний навіть для простих запитів, але він має вирішальне значення, якщо мова йде про об'єднання та запити, трохи складніші ніж a select top 1 [ColumnName] from [TableName].

  2. Після правильного відступу ніщо не забороняє додавати коментарі до самого запиту, коли це доречно. Не зловживайте ними: якщо код достатньо явний, додавання коментарів просто зашкодить ясності коду. Але вони все ще вітаються для менш чітких частин запиту.

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

  3. Застосування того ж стилю над таблицями, стовпцями тощо також дуже допомагає читабельності. Коли спадок база даних таблиць PRODUCT, users, USERS_ObsoleteDONT_USE, PR_SHIPMENTSі HRhbYd_UU, хто - то робить що - то дуже неправильно.

  4. Важливим є також використання одного стилю над запитами . Наприклад, якщо ви пишете запити для Microsoft SQL Server, і ви вирішили використовувати [TableName]замість цього TableName, дотримуйтесь цього. Якщо ви переходите до нового рядка після "" select, не робіть цього лише в половині запитів, але всі вони.

  5. Не використовуйте* , якщо немає вагомих причин для цього (наприклад, if exists(select * from [TableName] where ...)у Microsoft SQL Server). *Має не тільки негативний вплив на ефективність у деяких (якщо не в більшості) базах даних, але це також не корисно для розробника, який використовує ваш запит. Таким же чином розробник повинен отримувати доступ до значень по імені, ніколи не за індексом.

  6. Нарешті, для селекціонерів немає нічого поганого в наданні виду . Для всього іншого, збережені процедури можуть також використовуватися залежно від проекту та людей, з якими ви працюєте².


¹ Деякі люди ненавидять збережені процедури. Інші не люблять їх з кількох (цілком справедливих, принаймні для них) причин.

² Ваші колеги, інші студенти, ваш вчитель тощо


9

Тут трохи постріл у темряві, але якщо ви пишете безліч тимчасових представлень, можливо, ви ще не зрозуміли, що в більшості місць ви можете помістити таблицю у SQL-виписку, цю таблицю можна замінити запитом.

Отже, замість приєднання таблиці A до тимчасового перегляду B, ви можете приєднати таблицю A до запиту, який ви використовували як тимчасовий вигляд B. Наприклад:

    SELECT A.Col1, A.Col2, B.Col1,B.Col2
      FROM (SELECT RealTableZ.Col1, RealTableY.Col2, RealTableY.ID as ID
              FROM RealTableZ 
   LEFT OUTER JOIN RealTableY
                ON RealTableZ.ForeignKeyY=RealTableY.ID
             WHERE RealTableY.Col11>14
            ) As B
        INNER JOIN A
                ON A.ForeignKeyY=B.ID

Цей приклад досить безглуздий, але повинен пояснити синтаксис.

Для представлень, які не є "спеціальними" (індексованими, розділеними), це має спричинити такий самий план запитів, як якщо б ви використовували подання.

Що стосується спрощення написання, ви можете перевірити кожен фрагмент, щоб переконатися, що ви отримаєте те, що очікуєте, перш ніж виписати весь запит.

Мої вибачення, якщо це вже стара капелюх до вас.


3
Я досить знаю щодо SQL, і я дуже ненавиджу цей відступ: він може виглядати непогано, але він абсолютно марний "на мій погляд". Дві причини: я не можу чітко зрозуміти, чи є це ліве зовнішнє з'єднання частиною основного запиту чи частиною підзапиту, йому потрібен красувач коду, і будь-коли, коли ви хочете додати кілька рядків, вам потрібно знову прикрасити весь текст . Відступ плану, який просто потребує TABS, набагато гнучкіший. Я не проголосував вашу відповідь, але дуже відштовхую тих, хто використовує цей стиль ... особливо коли їм потрібна моя допомога.
Алессандро Россі

7

Замість тимчасових представлень використовуйте пункт WITH . Це значно спрощує розбиття великих запитів на більш читабельні менші частини.


1
Якщо ви використовуєте cte, майте на увазі, що запит зберігається лише до запуску наступного запиту, тому в деяких випадках, коли ви використовуєте cte в декількох запитах, для продуктивності може бути краще використовувати таблицю temp.
Рейчел

3
  1. Познайомтеся з теорією множин, якщо ви ще цього не зробили. SQL базується на теорії наборів, і більш детальне розуміння наборів допоможе вам ознайомитись із тим, як працює SQL.
  2. Практикуйте більше SQl, якщо ви просто вивчаєте SQL, його знадобиться час, щоб зрозуміти, як все робити, щось просто потребує часу, перш ніж ви дійсно їх зрозумієте, приєднання - чудовий приклад, чим більше ви їх використовуєте, тим краще ви отримаєте в ньому.
  3. Переконайтесь, що таблиці, які ви запитуєте, правильно розроблені
  4. Не бійтеся використовувати погляди на вибрані запити, особливо якщо у вас є спільний набір, який потребує вдосконалення кількома різними способами

1

Як і все інше, ви хочете розбити проблему на керовані частини.

Це дійсно ТАК, як ви, до речі, вирішуєте складні проблеми.

Отже: Ви хочете перевірити підзапит, щоб побачити, що він дійсно повертає те, що ви хочете, перш ніж виконувати на ньому зовнішній запит. Ви хочете спробувати мінімальне приєднання кожної таблиці, до якої ви приєднуєтесь, щоб ви могли бачити, що ви справді продумуєте її належним чином. Такі речі. Сподіватися набрати все це і вийти саме те, що ви хочете одним ударом, просто нереально.

Після того, як він досягне певного рівня складності, оператор SQL - це фактично сама по собі програма. Це має велику різницю, щоб реально зрозуміти, як дані поєднуються, відбираються, фільтруються та виводяться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.