Содержание

Оператор SQL SELECT: примеры, синтаксис

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

Оператор SQL SELECT имеет следующий синтаксис:

SELECT column_list
FROM table_name
[WHERE сondition
GROUP BY expression
HAVING condition
ORDER BY expression]

Необязательные операторы обрамлены квадратными скобками [].

В параметре column_list указываются названия столбцов таблицы, которые необходимо вывести, либо символ “*”, позволяющий вывести все столбцы таблицы. Ключевым словом FROM задается название таблицы или таблиц, из которых следует брать столбцы. Оператор SQL WHERE задает дополнительные условия выборки. Оператор SQL GROUP BY используют для группирования результата по столбцу или по нескольким столбцам.

Оператор SQL HAVING включают в запрос для задания условия агрегатных функций. Наконец, оператор SQL ORDER BY используется для сортировки значений.


Примеры оператора SQL SELECT. Имеется следующая таблица Planets:

IDPlanetNameRadiusSunSeason
OpeningYearHavingRingsOpener
1Mars33966871659NoChristiaan Huygens
2Saturn6026810759.22Yes
3Neptune24764601901846YesJohn Couch Adams
4Mercury2439115. 881631NoNicolaus Copernicus
5Venus60512431610NoGalileo Galilei

Пример 1. С помощью оператора SQL SELECT вывести названия планет (Name):

SELECT PlanetName FROM Planets

Результат:

PlanetName
Mars
Saturn
Neptune
Mercury
Venus

Пример 2. С помощью оператора SQL SELECT вывести названия планет, у которых есть кольца (HavingRings):

SELECT PlanetName FROM Planet WHERE HavingRings = 'Yes'

Результат:

PlanetName
Saturn
Neptune

Пример 3.  С помощью оператора SQL SELECT вывести информацию о планете Нептун:

SELECT * FROM Planets WHERE PlanetName = 'Neptune'

Результат:

IDPlanetNameRadiusSunSeason
OpeningYearHavingRingsOpener
3Neptune24764601901846YesJohn Couch Adams

Справочник SQL для выражений запросов, применяемых в ArcGIS—ArcGIS Pro

This topic describes the elements of common selection queries in ArcGIS. Выражения запросов в ArcGIS используют SQL.

Внимание:

Синтаксис SQL не работает при вычислении полей с помощью окна Калькулятора поля .

Часто используемые запросы: поиск строк

Строковые значения в выражениях всегда заключаются в одинарные кавычки, например:

STATE_NAME = 'California'

Строки в выражениях чувствительны к регистру, кроме случаев работы в базах геоданных в Microsoft SQL Server. Чтобы выполнять не чувствительный к регистру поиск в других источниках данных, можно использовать функцию SQL для преобразования всех значений в один регистр. Для источников данных на основе файлов, таких как файловые базы геоданных или шейп-файлы, для задания регистра выборки можно использовать функции UPPER или LOWER. Например, при помощи следующего выражения выбирается штат, имя которого написано как ‘Rhode Island’ или ‘RHODE ISLAND’:

UPPER(STATE_NAME) = 'RHODE ISLAND'

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

NAME = 'Alfie''s Trough'

При помощи оператора LIKE (вместо оператора = ) строится поиск частей строк. Например, данное выражение выбирает Mississippi и Missouri среди названий штатов США:

STATE_NAME LIKE 'Miss%'

Символ процента (%) означает, что на этом месте может быть что угодно – один символ или сотня, или ни одного. Если вы хотите использовать групповой символ, обозначающий один любой символ, используйте символ подчёркивания (_). Следующий пример показывает выражение для выбора имен Catherine Smith и Katherine Smith:

OWNER_NAME LIKE '_atherine Smith'

Можно также использовать операторы больше (>), меньше (<), больше или равно (>=), меньше или равно (<=), не равно (<>) и BETWEEN, чтобы выбирать строковые значения на основании их сортировки. Например, этот запрос выбирает все города в покрытии, названия которых начинаются с букв от М до Z:

CITY_NAME >= 'M'

Строковые функции могут использоваться для форматирования строк. Например функция LEFT возвращает определенное количество символов начиная с левого края строки. Данный запрос возвращает все штаты, начинающиеся на букву A:

LEFT(STATE_NAME,1) = 'A'

Список поддерживаемых функций вы найдете в документации по своей СУБД.

Часто используемые выражения: поиск значений NULL

Вы можете использовать ключевое слово NULL, чтобы отбирать объекты и записи, содержащие пустые поля. Перед ключевым словом NULL всегда стоит IS или IS NOT. Например, чтобы найти города, для которых не была введена численность населения по данным переписи 1996 года, можно использовать следующее выражение:

POPULATION IS NULL

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

POPULATION96 IS NOT NULL

Часто используемые выражения: поиск чисел

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

Вы можете запрашивать цифровые значения, используя операторы равно (=), не равно (<>), больше (>), меньше (<), больше или равно (>=) и меньше или равно (<=), а также BETWEEN (между), например:

POPULATION >= 5000

Числовые функции можно использовать для форматирования чисел. Например функция ROUND округляет до заданного количества десятичных знаков данные в файловой базе геоданных:

ROUND(SQKM,0) = 500

Список поддерживаемых числовых функций см. в документации по СУБД.

Даты и время

Общие правила и часто используемые выражения

В таких источниках данных, как база геоданных, даты хранятся в полях даты–времени. Однако в шейп-файлах это не тек. Поэтому большинство из примеров синтаксиса запроса, представленных ниже, содержит ссылки на время. В некоторых случаях часть запроса, касающаяся времени, может быть без всякого вреда пропущена, когда известно, что поле содержит только даты; в других случаях её необходимо указывать, или запрос вернет синтаксическую ошибку.

Поиск полей с датой требует внимания к синтаксису, необходимому для источника данных. Если вы создаете запрос в Конструкторе запросов в режиме Условие, правильный синтаксис будет сгенерирован автоматически. Ниже приведен пример запроса, который возвращает все записи после 1 января 2011, включительно, из файловой базы геоданных:

INCIDENT_DATE >= date '2011-01-01 00:00:00'

Даты хранятся в исходной базе данных относительно 30 декабря 1899 года, 00:00:00. Это действительно для всех источников данных, перечисленных здесь.

Цель этого подраздела – помочь вам в построении запросов по датам, но не по значениям времени. Когда со значением даты хранится не нулевое значение (например January 12, 1999, 04:00:00), то запрос по дате не возвратит данную запись, поскольку если вы задаете в запросе только дату для поля в формате дата – время, недостающие поля времени заполняются нулями, и выбраны будут только записи, время которых соответствует 12:00:00 полуночи.

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

  • Строка, отображаемая в SQL-запросе, может иметь только небольшое сходство со значением, показанным в таблице, особенно когда в нее входит время. Например время, введенное как 00:00:15, отображается в атрибутивной таблице как 12:00:15 AM с региональными настройками США, а сопоставимый синтаксис запроса Datefield = ‘1899-12-30 00:00:15’.
  • Атрибутивная таблица не имеет сведений об исходных данных, пока вы не сохраните изменения. Она сначала попытается отформатировать значения в соответствии с ее собственным форматом, затем, после сохранения изменений, она попытается подогнать получившиеся результаты в соответствии с базой данных. По этой причине, вы можете вводить время в шейп-файл, но обнаружите, что оно удаляется при сохранении ваших изменений. Поле будет содержать значение ‘1899-12-30’, которое будет отображаться как 12:00:00 AM или эквивалентно, в зависимости от ваших региональных настроек.

Синтаксис даты-времени для многопользовательских баз геоданных

Oracle
Datefield = date 'yyyy-mm-dd'

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

Альтернативный формат при запросах к датам в Oracle следующий:

Datefield = TO_DATE('yyyy-mm-dd hh:mm:ss','YYYY-MM-DD Hh34:MI:SS')

Второй параметр ‘YYYY-MM-DD Hh34:MI:SS’ описывает используемый при запросах формат. Актуальный запрос выглядит так:

Datefield = TO_DATE('2003-01-08 14:35:00','YYYY-MM-DD Hh34:MI:SS')

Вы можете использовать более короткую версию:

TO_DATE('2003-11-18','YYYY-MM-DD')

И снова записи, где время не равно нулю, не будут возвращены.

SQL Server
Datefield = 'yyyy-mm-dd hh:mm:ss'

Часть запроса hh:mm:ss может быть опущена, когда в записях не установлено время.

Ниже приведен альтернативный формат:

Datefield = 'mm/dd/yyyy'
IBM Db2
Datefield = TO_DATE('yyyy-mm-dd hh:mm:ss','YYYY-MM-DD Hh34:MI:SS')

Часть запроса hh:mm:ss не может быть опущена, даже если время равно 00:00:00.

PostgreSQL
Datefield = TIMESTAMP 'YYYY-MM-DD Hh34:MI:SS'
Datefield = TIMESTAMP 'YYYY-MM-DD'

Вы должны указать полностью временную метку при использовании запросов типа «равно», в или не будет возвращено никаких записей. Вы можете успешно делать запросы со следующими выражениями, если запрашиваемая таблица содержит записи дат с точными временными метками (2007-05-29 00:00:00 или 2007-05-29 12:14:25):

select * from table where date = '2007-05-29 00:00:00';

или

select * from table where date = '2007-05-29 12:14:25';

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

select * from table where date < '2007-05-29';
select * from table where date < '2007-05-29 12:14:25';
Файловые базы геоданных, шейп-файлы, покрытия и прочие файловые источники данных
Datefield = date 'yyyy-mm-dd'

Файловые базы геоданных поддерживают использование времени в поле даты, поэтому его можно добавить в выражение:

Datefield = date 'yyyy-mm-dd hh:mm:ss'

Шейп-файлы и покрытия не поддерживают использование времени в поле даты.

SQL, используемый в файловой базе геоданных, базируется на стандарте SQL-92.

Известные ограничения

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

Запрос к датам левой части соединения будет выполнен успешно, если использовать ограниченную версию SQL, разработанную для файловых источников данных. Если вы не используете такой источник данных, можете перевести выражение для использования этого формата. Нужно обеспечить, чтобы выражение запроса включало поля из более чем одной присоединенной таблицы. Например, если соединены класс пространственных объектов и таблица (FC1 и Table1), и они поступают из многопользовательской базы геоданных, следующее выражение не будет выполнено или не вернет данные:

FC1. date = date #01/12/2001#
FC1.date = date '01/12/2001'

Чтобы запрос был выполнен успешно, можно создать вот такой запрос:

FC1.date = date '01/12/2001' and Table1.OBJECTID > 0

Так как запрос включает поля из обеих таблиц, будет использована ограниченная версия SQL. В этом выражении Table1.OBJECTID всегда > 0 для записей, которые сопоставлены в процессе создания соединения, поэтому это выражение всегда верно для всех строк, содержащих сопоставления соединения.

Чтобы быть уверенным, что каждая запись с FC1.date = date ’01/12/2001′ выбрана, используйте следующий запрос:

FC1.date = date '01/12/2001' and (Table1.OBJECTID IS NOT NULL OR Table1.OBJECTID IS NULL)

Такой запрос будет выбирать все записи с FC1.date = date ’01/12/2001′, независимо от того, есть ли сопоставление при соединении для каждой отдельной записи.

Комбинированные выражения

Составные запросы могут комбинироваться путем соединения выражений операторами AND (И) и OR (ИЛИ). Вот пример запроса для выборки всех домов с общей площадью более 1500 квадратных футов и гаражом более чем на три машины:

AREA > 1500 AND GARAGE > 3

Когда вы используете оператор OR (ИЛИ), по крайней мере одно из двух разделенных оператором выражений, должно быть верно для выбираемой записи, например:

RAINFALL < 20 OR SLOPE > 35

Используйте оператор NOT (НЕ) в начале выражения, чтобы найти объекты или записи, не соответствующие условию выражения, например:

NOT STATE_NAME = 'Colorado'

Оператор NOT можно комбинировать с AND и OR. Вот пример запроса, который выбирает все штаты Новой Англии за исключением штата Maine:

SUB_REGION = 'New England' AND NOT STATE_NAME = 'Maine'

Вычисления

Вычисления можно включить в запросы с помощью математических операторов +, –, * и /. Можно использовать вычисление между полем и числом, например:

AREA >= PERIMETER * 100

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

POP1990 / AREA <= 25

Приоритет выражения в скобках

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

HOUSEHOLDS > MALES * (POP90_SQMI + AREA)

Вы можете добавить скобки в режиме Редактирование SQL вручную, или использовать команды Группировать и Разгруппировать в режиме Условие, чтобы добавить или удалить их.

Подзапросы

Подзапрос – это запрос, вложенный в другой запрос и поддерживаемый только в базах геоданных. Подзапросы могут использоваться в SQL-выражении для применения предикативных или агрегирующих функций, или для сравнения данных со значениями, хранящимися в другой таблице и т.п. Это может быть сделано с помощью ключевых слов IN или ANY. Например этот запрос выбирает только те страны, которых нет в таблице indep_countries:

COUNTRY_NAME NOT IN (SELECT COUNTRY_NAME FROM indep_countries)

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

Этот запрос возвращает объекты, где GDP2006 больше, чем GDP2005 любых объектов, содержащихся в countries (странах):

GDP2006 > (SELECT MAX(GDP2005) FROM countries)

Поддержка подзапросов в файловых базах геоданных ограничена следующим:

Операторы

Ниже приведен полный список операторов, поддерживаемых файловыми базами геоданных, шейп-файлами, покрытиями и прочими файловыми источниками данных. Они также поддерживаются в многопользовательских базах геоданных, хотя для этих источников данных может требоваться иной синтаксис. Кроме нижеперечисленных операторов, многопользовательские базы геоданных поддерживают дополнительные возможности. Более подробную информацию см. в документации по своей СУБД.

Арифметические операторы

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

ОператорОписание

*

Арифметический оператор умножения

/

Арифметический оператор деления

+

Арифметический оператор сложения

Арифметический оператор вычитания

Арифметические операторы

Операторы сравнения

Операторы сравнения используются для сравнения одного выражения с другим.

ОператорОписание

<

Меньше . Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат.

<=

Меньше или равно. Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат.

<>

Не равно . Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат.

>

Больше . Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат.

>=

Больше или равно. Может использоваться со строками (сравнение основывается на алфавитном порядке) и для числовых вычислений, а также дат.

[NOT] BETWEEN x AND y

Выбирает запись, если она имеет значение, которое больше или равно x и меньше или равно y. Если перед ней стоит значение NOT, она выбирает запись, если та имеет значение вне указанного диапазона. Например это выражение выбирает все записи со значениями, которые больше или равны 1 и меньше или равны 10:

OBJECTID BETWEEN 1 AND 10

Вот эквивалент этого выражения:

OBJECTID >= 1 AND OBJECTID <= 10

Однако, выражение с оператором BETWEEN обрабатывается быстрее, если у вас поле проиндексировано.

[NOT] EXISTS

Возвращает TRUE (истинно), если подзапрос возвращает хотя бы одну запись; в противном случае возвращает FALSE (ложно). Например, данное выражение вернет TRUE, если поле OJBECTID содержит значение 50:

EXISTS (SELECT * FROM parcels WHERE OBJECTID = 50)

EXISTS поддерживается только в файловых и многопользовательских базах геоданных.

[NOT] IN

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

STATE_NAME IN ('Alabama', 'Alaska', 'California', 'Florida')

IS [NOT] NULL

Выбирает запись, если там в определенном поле есть нулевое значение. Если перед NULL стоит NOT, выбирает запись, где в определенном поле есть какое-то значение.

x [NOT] LIKE y [ESCAPE ‘escape-character’]

Используйте оператор LIKE (вместо оператора = ) с групповыми символами, если хотите построить запрос по части строки. Символ процента (%) означает, что на этом месте может быть что угодно – один символ или сотня, или ни одного. Если вы хотите использовать групповой символ, обозначающий один любой символ, используйте символ подчёркивания (_). Если вам нужен доступ к несимвольным данным, используйте функцию CAST. Например, этот запрос возвращает числа, начинающиеся на 8, из целочисленного поля SCORE_INT:

CAST (SCORE_INT AS VARCHAR(10)) LIKE '8%'

Для включения символа (%) или (_) в вашу строку поиска, используйте ключевое слово ESCAPE для указания другого символа вместо escape, который в свою очередь обозначает настоящий знак процента или подчёркивания. Например данное выражение возвращает все строки, содержащие 10%, такие как 10% DISCOUNT или A10%:

AMOUNT LIKE '%10$%%' ESCAPE '$'
Операторы сравнения

Логические операторы

ОператорОписание

AND

Соединяет два условия и выбирает запись, в которой оба условия являются истинными. Например, выполнение следующего запроса выберет все дома с площадью более 1 500 квадратных футов и гаражом на две и более машины:

AREA > 1500 AND GARAGE > 2

OR

Соединяет два условия и выбирает запись, где истинно хотя бы одно условие. Например выполнение следующего запроса выберет все дома с площадью более 1,500 квадратных футов или гаражом на две и более машины:

AREA > 1500 OR GARAGE > 2

NOT

Выбирает записи, не соответствующие указанному выражению. Например это выражение выберет все штаты, кроме Калифорнии (California):

NOT STATE_NAME = 'California'
Логические операторы

Операторы строковой операции

Оператор Описание
||

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

FIRST_NAME || MIDDLE_NAME || LAST_NAME

Функции

Ниже приведен полный список функций, поддерживаемых файловыми базами геоданных, шейп-файлами, покрытиями и прочими файловыми источниками данных. Функции также поддерживаются в многопользовательских базах геоданных, хотя в этих источниках данных может использоваться иной синтаксис или имена функций. Кроме нижеперечисленных функций, многопользовательские базы геоданных поддерживают дополнительные возможности. Более подробную информацию см. в документации по своей СУБД.

Функции дат

ФункцияОписание

CURRENT_DATE

Возвращает текущую дату.

EXTRACT(extract_field FROM extract_source)

Возвращает фрагмент extract_field из extract_source. Аргумент extract_source является выражением даты–времени. Аргументом extract_field может быть одно из следующих ключевых слов: YEAR, MONTH, DAY, HOUR, MINUTE или SECOND.

CURRENT TIME

Возвращает текущую дату.

Функции дат

Строковые функции

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

Аргументы, обозначаемые character_exp, являются строками символов переменной длины.

Аргументы, указанные как start или length могут быть числовыми постоянными или результатами других скалярных функций, где исходные данные представлены числовым типом.

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

ФункцияОписание

CHAR_LENGTH(string_exp)

Возвращает длину строкового выражения в символах.

LOWER(string_exp)

Возвращает строку, идентичную string_exp, в которой все символы верхнего регистра изменены на символы нижнего регистра.

POSITION(character_exp IN character_exp)

Возвращает место первого символьного выражения во втором символьном выражении. Результат – число с точностью, определяемой реализацией и коэффициентом кратности 0.

SUBSTRING(string_exp FROM start FOR length)

Возвращает символьную строку, извлекаемую из string_exp, начинающуюся с символа, положение которого определяется символами start и length .

TRIM(BOTH | LEADING | TRAILING trim_character FROM string_exp)

Возвращает string_exp, укороченную на количество символов, указанное в аргументе trim_character, с начала, с конца или с обоих концов строки.

UPPER(string_exp)

Возвращает строку, идентичную string_exp, в которой все символы нижнего регистра изменены на символы верхнего регистра.

Строковые функции

Числовые функции

Все числовые функции возвращают числовые значения.

Аргументы, обозначенные numeric_exp, float_exp или integer_exp могут быть именем столбца, результатом другой скалярной функции или числовой константой, где исходные данные могут быть представлены числовым типом.

ФункцияОписание

ABS(numeric_exp)

Возвращает абсолютное значение numeric_exp.

ACOS(float_exp)

Возвращает угол в радианах, равный арккосинусу float_exp.

ASIN(float_exp)

Возвращает угол в радианах, равный арксинусу float_exp.

ATAN(float_exp)

Возвращает угол в радианах, равный арктангенсу float_exp.

CEILING(numeric_exp)

Возвращает наименьшее целочисленное значение, большее или равное numeric_exp.

COS(float_exp)

Возвращает косинус float_exp, где float_exp — угол, выраженный в радианах.

FLOOR(numeric_exp)

Возвращает наибольшее целое значение, меньшее или равное numeric_exp.

LOG(float_exp)

Возвращает натуральный логарифм float_exp.

LOG10(float_exp)

Возвращает логарифм по основанию 10 float_exp.

MOD(integer_exp1, integer_exp2)

Возвращает результат деления integer_exp1 на integer_exp2.

POWER(numeric_exp, integer_exp)

Возвращает значение numeric_exp в степени integer_exp.

ROUND(numeric_exp, integer_exp)

Возвращает numeric_exp, округленное до integer_exp знаков справа от десятичной точки. Если integer_exp отрицательное, numeric_exp округляется до |integer_exp| знаков слева от десятичной запятой.

SIGN(numeric_exp)

Возвращает указатель знака numeric_exp. Если numeric_exp меньше нуля, возвращается -1. Если numeric_exp равно нулю, возвращается 0. Если numeric_exp больше нуля, возвращается 1.

SIN(float_exp)

Возвращает синус float_exp, где float_exp — угол, выраженный в радианах.

TAN(float_exp)

Возвращает тангенс float_exp, где float_exp — угол, выраженный в радианах.

TRUNCATE(numeric_exp, integer_exp)

Возвращает numeric_exp, округленное до integer_exp знаков справа от десятичной точки. Если integer_exp отрицательное, numeric_exp округляется до |integer_exp| знаков слева от десятичной запятой.

Числовые функции

Функция CAST

Функция CAST конвертирует значение в определенный тип данных. Синтаксис выглядит так:

CAST(exp AS data_type [(length)])

Пример:

CAST (SCORE_INT AS VARCHAR(10))

Аргумент exp может быть названием столбца, результатом другой скалярной функции или буквенным. Data_type может быть любым из следующих ключевых слов, и задается строчными или заглавными буквами: CHAR, VARCHAR, INTEGER, SMALLINT, REAL, DOUBLE, DATE, TIME, DATETIME, NUMERIC или DECIMAL.

Более подробно о функции CAST см. CAST and CONVERT.

Связанные разделы

Отзыв по этому разделу?

SQL Server Пример Запроса Связанного Сервера



Находясь в Management Studio, я пытаюсь выполнить запрос/выполнить соединение между двумя связанными серверами. Является ли это правильным синтаксисом с использованием связанных серверов БД:

select foo.id 
from databaseserver1.db1.table1 foo, 
     databaseserver2.db1.table1 bar 
where foo.name=bar.name

В принципе, вы просто предисловуете имя сервера БД к db.table ?

sql-server linked-server
Поделиться Источник bmw0128     03 ноября 2010 в 21:44

12 ответов


  • Настройка связанного сервера SSMS на DB2

    У меня есть локальный экземпляр SQL Server, на котором я создал соединение связанного сервера с базой данных DB2 с именем DB2OurDatabase.

    при создании соединения связанного сервера я указал UID и PWD, которые я использую в различных инструментах запроса или приложениях для запроса…

  • SQL Server 2008 настройка строки подключения связанного сервера

    Я пытаюсь настроить связанный сервер на другой экземпляр SQL Server, установленный на том же сервере Windows. В консоли управления SQL Server у меня добавлены оба экземпляра, и я пытаюсь сделать вставку из одной базы данных в другую. Я настраиваю связанный сервер с помощью приведенного ниже…



186

Формат, вероятно, должен быть:

<server>.<database>.<schema>.<table>

Например: DatabaseServer1.db1.dbo.table1


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

А именно, при запросе к связанному серверу в ситуации соединения таблица ENTIRE со связанного сервера, скорее всего, будет загружена на сервер, с которого выполняется запрос, чтобы выполнить операцию соединения. В случае OP оба table1 из DB1 и table1 из DB2 будут полностью переданы серверу, выполняющему запрос, предположительно с именем DB3 .

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

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

Если это невозможно, то вам нужно посмотреть на различные вещи, которые могут привести к тому, что серверу SQL придется загружать всю таблицу локально. Например, используя GETDATE() или даже определенные соединения. Другие убийцы производительности включают в себя не предоставление соответствующих прав.

См . http://thomaslarock.com/2013/05/top-3-performance-killers-for-linked-server-queries/ для получения дополнительной информации.

Поделиться NotMe     03 ноября 2010 в 21:47



32

SELECT * FROM OPENQUERY([SERVER_NAME], 'SELECT * FROM DATABASE_NAME..TABLENAME')

Это может вам помочь.

Поделиться Akhilesh Kamate     16 марта 2016 в 12:18



10

Если вы все еще находите проблему с <server>.<database>.<schema>.<table>

Вложите имя сервера в []

Поделиться Mian     13 августа 2013 в 18:21


  • OPENDATASOURCE вместо связанного сервера

    У меня есть ситуация, когда связанный сервер с access DB приводит к сбою моего сервера SQL. Сбой здесь означает, что добавление связанного сервера приводит к тому, что все другие связанные серверы, использующие этот поставщик, перестают работать. Любые запросы к этим связанным серверам зависают и…

  • SQL обновление связанного сервера синтаксическая ошибка Openquery

    Я пытаюсь обновить данные в бэкэнде PervasiveSQL (система Sage ERP) с SQL Server 2008 R2 через настройку связанного сервера. Ниже приведены подробные сведения и возвращенная ошибка msg… Кикер заключается в том, что оператор update работает на коробке разработки просто отлично, очень похожая…



9

Для тех, у кого возникли проблемы с этими другими ответами , попробуйте OPENQUERY

Пример:

 SELECT * FROM OPENQUERY([LinkedServer], 'select * from [DBName].[schema].[tablename]') 

Поделиться Tom Stickel     07 февраля 2017 в 18:45



8

Вам нужно указать схему/владельца (dbo по умолчанию) как часть ссылки. Кроме того, было бы предпочтительнее использовать более новый стиль соединения (ANSI-92).

select foo.id 
    from databaseserver1.db1.dbo.table1 foo
        inner join databaseserver2.db1.dbo.table1 bar 
            on foo.name = bar.name

Поделиться Joe Stefanelli     03 ноября 2010 в 21:58



6

select * from [Server].[database].[schema].[tablename] 

Это правильный способ позвонить. Перед выполнением запроса обязательно убедитесь, что серверы связаны!

Чтобы проверить наличие связанных серверов позвоните:

EXEC sys.sp_linkedservers 

Поделиться Abhishek Jaiswal     10 декабря 2015 в 10:11



4

select name from drsql01.test.dbo.employee
  • drslq01-это servernmae-linked serer
  • тест-это имя базы данных
  • dbo is schema-схема по умолчанию
  • сотрудник-это имя таблицы

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

Поделиться Jaspreet Singh     15 января 2018 в 03:22



2

Обычно прямые запросы не должны использоваться в случае связанного сервера, поскольку он сильно использует временную базу данных сервера SQL. На первом этапе данные извлекаются в temp DB, а затем происходит фильтрация. Есть много тем об этом. Лучше использовать open OPENQUERY, потому что он передает SQL на исходный связанный сервер, а затем возвращает отфильтрованные результаты, например

SELECT *
FROM OPENQUERY(Linked_Server_Name , 'select * from TableName where ID = 500')

Поделиться Muhammad Yaseen     02 марта 2016 в 15:12



2

Как бы то ни было, я нашел следующий синтаксис, который работает лучше всего:

SELECT * FROM [LINKED_SERVER]…[TABLE]

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

Поделиться Sean Warren     24 октября 2017 в 14:41



2

щелкните правой кнопкой мыши на таблице и выберите пункт script table as select

Поделиться Shimon Doodkin     25 июня 2018 в 05:14



0

Следующий запрос работает лучше всего.

Попробуйте выполнить этот запрос:

SELECT * FROM OPENQUERY([LINKED_SERVER_NAME], 'SELECT * FROM [DATABASE_NAME].[SCHEMA].[TABLE_NAME]')

Это очень помогает связать MySQL С MS SQL

Поделиться Vijay S     25 июня 2018 в 05:43



0

PostgreSQL :

  1. Вы должны указать имя базы данных в источнике данных DSN .
  2. Запустите Management Studio от имени администратора
  3. Вы должны опустить DBName из запроса :

    SELECT * FROM OPENQUERY([LinkedServer], 'select * from schema."tablename"')

Поделиться Shadi Namrouti     03 июня 2020 в 20:23


Похожие вопросы:


SQL 2005 Запроса Связанного Сервера Периодически Не

У нас есть база данных, работающая на SQL 2005. Одна из процедур хранилища ищет адрес пользователя email из Active Directory с помощью связанного сервера. Вызов связанного сервера происходит в…


SQL Server производительность связанного сервера

Я использую SQL Server 2008 Enterprise. И я использую технологии Linked Server для связи другого экземпляра SQL Server 2008 Enterprise с другим сервером. Я пишу TSQL для манипулирования объектами…


Можно ли установить SQL Server тайм-аут удаленного запроса на запрос для вызовов связанного сервера?

Для связанных серверов я вижу, как можно изменить конфигурацию remote query timeout, чтобы намекнуть, что вызов связанного сервера должен завершиться или откатиться в пределах определенного значения…


Настройка связанного сервера SSMS на DB2

У меня есть локальный экземпляр SQL Server, на котором я создал соединение связанного сервера с базой данных DB2 с именем DB2OurDatabase. при создании соединения связанного сервера я указал UID и. ..


SQL Server 2008 настройка строки подключения связанного сервера

Я пытаюсь настроить связанный сервер на другой экземпляр SQL Server, установленный на том же сервере Windows. В консоли управления SQL Server у меня добавлены оба экземпляра, и я пытаюсь сделать…


OPENDATASOURCE вместо связанного сервера

У меня есть ситуация, когда связанный сервер с access DB приводит к сбою моего сервера SQL. Сбой здесь означает, что добавление связанного сервера приводит к тому, что все другие связанные серверы,…


SQL обновление связанного сервера синтаксическая ошибка Openquery

Я пытаюсь обновить данные в бэкэнде PervasiveSQL (система Sage ERP) с SQL Server 2008 R2 через настройку связанного сервера. Ниже приведены подробные сведения и возвращенная ошибка msg… Кикер…


Ошибка при создании связанного сервера в SQL Server 2008R2

Когда я создаю связанный сервер в SQL Server, он вызывает ошибку Не удается создать экземпляр OLEDB provider SQLNCLI10 для связанного сервера ‘ linked server name ‘(microsoft sql server error 7302). ..


SQL Server запросы связанного сервера w/ ANSI_WARNINGS OFF

Я пытаюсь использовать функцию связанного сервера в SQL Server (2014) для выполнения кросс-серверного запроса (вычисления) из хранимой процедуры. Хранимая процедура изначально была разработана для…


MongoDb ODBC драйвер -> SQL Server сбой запроса связанного сервера

У меня установлен MongoDb 3.4 и я пытаюсь получить его данные из SQL Server 2019 dev. edition с помощью связанного сервера. Мне удалось установить драйвер MongoDb ODBC и разъем MongoDB для BI 2.13 и…

Несколько примеров рекурсивных SQL-запросов для системы DIRECTUM | Статья

Чтобы понять рекурсию, нужно сначала понять рекурсию.

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

Пожалуй, одним определением и ограничусь, в сети масса информации на эту тему.

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

В стандартной поставке системы DIRECTUM есть ряд справочников, которые можно считать рекурсивными. Такие справочники содержат реквизит, сгенерированный по этому же справочнику (Подразделения, Поручения, РКК, Договоры и т.д.).

Косвенно рекурсивным можно считать справочники Работников (через Подразделения: в Работниках есть реквизит Подразделение, в Подразделении указан Руководитель — работник).

Кроме того, рекурсивной можно считать таблицу задач. Косвенно рекурсивной таблицу заданий (через задачи).

Построим несколько запросов на примере справочника Подразделения. Стандартный справочник Подразделения в DIRECTUM можно считать рекурсивным, так как в нем есть реквизит, который ссылается на сам справочник Подразделения: Головное подразделение. Фактически, любой из примеров легко переделать для другого справочника или таблиц ЗЗУ.

Пример 1

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

-----------------------------------------------------------------
-- Иерархия подразделений
-----------------------------------------------------------------
with DipartmentHiererhcy (
  ID,
  HightID, 
  Level)
as
(
-- Подразделение верхнего уровня (N = 0)
  select
    department.Analit,
    department.Podr,
    0 as Level
  from
    MBAnalit department
  where
    department.Podr is null
    and department.vid = 
  union ALL
-- Подчиненное подразделение (N + 1)
  select
    department.Analit,
    department.Podr,
    Level + 1
  from
    MBAnalit as department
      inner join DipartmentHiererhcy as hightdepartment
        on department.Podr = hightdepartment.ID
  where
    department.vid = 
)
-- Иерархия подразделений
select
  hierarchy. ID as [ИД],
  department.NameAn as [Подразделение],
  IsNull(hightdepartment.NameAn, '') as [Ведущее подразделение],
  Level as [Уровень]
from
  DipartmentHiererhcy hierarchy
    left join MBAnalit department
      on department.Analit = hierarchy.ID
   left join MBAnalit hightdepartment
      on hightdepartment.Analit = hierarchy.HightID

Результат этого запроса на тестовой базе: список подразделений с указанием ведущего и уровня в иерархии.

Пример 2

Запрос можно модифицировать и под конкретные задачи. Например, при разработке отчетов по определенному подразделению необходимо учитывать не только указанное, но и все подчиненные подразделения. В этом случае можно получить все дерево таким запросом:

-----------------------------------------------------------------
-- Иерархия подразделений вниз от указанного
-----------------------------------------------------------------
with DipartmentHiererhcy (
  ID,
  HightID, 
  Level)
as
(
-- Подразделение верхнего уровня (N = 0)
  select
    department. Analit,
    department.Podr,
    0 as Level
  from
    MBAnalit department
  where
    department.Analit = 
    and department.vid = 
  union ALL
-- Подчиненное подразделение (N + 1)
  select
    department.Analit,
    department.Podr,
    Level + 1
  from
    MBAnalit as department
      inner join DipartmentHiererhcy as hightdepartment
        on department.Podr = hightdepartment.ID
  where
    department.vid = 
)
-- Иерархия подразделений вниз от указанного
select
  hierarchy.ID as [ИД],
  department.NameAn as [Подразделение],
  IsNull(hightdepartment.NameAn, '') as [Ведущее подразделение],
  Level as [Уровень]
from
  DipartmentHiererhcy hierarchy
    left join MBAnalit department
      on department.Analit = hierarchy.ID
   left join MBAnalit hightdepartment
      on hightdepartment.Analit = hierarchy.HightID

Пример 3

Также может возникнуть необходимость получить данные по всем подчиненным указанного работника:

-----------------------------------------------------------------
-- Список подчиненных указанного работника
-----------------------------------------------------------------
with DipartmentHiererhcy (
  ID,
  HightID, 
  Level)
as
(
-- Подразделение верхнего уровня (N = 0)
  select
    department. Analit,
    department.Podr,
    0 as Level
  from
    MBAnalit department
  where
    department.FIO = 
    and department.vid = 
  union ALL
-- Подчиненное подразделение (N + 1)
  select
    department.Analit,
    department.Podr,
    Level + 1
  from
    MBAnalit as department
      inner join DipartmentHiererhcy as hightdepartment
        on department.Podr = hightdepartment.ID
  where
    department.vid = 
)
-- Список подчиненных указанного работника
select distinct
  department.NameAn as [Подразделение],
  employee.NameAn as [Работник],
  IsNull(chiefemployee.NameAn, '') as [Руководитель],
  Level as [Уровень]
from
  DipartmentHiererhcy hierarchy
    left join MBAnalit department
      on department.Analit = hierarchy.ID
   left join MBAnalit hightdepartment
      on hightdepartment.Analit = hierarchy.HightID
   left join MBAnalit employee
     on department.Analit = employee.Podr and employee.Vid = 
   left join MBAnalit chiefemployee
     on department.FIO = chiefemployee.Analit and chiefemployee. Vid = 
where
  employee.Analit is not null

Пример 4

Обратный к примеру 3: цепочка руководителей указанного работника по иерархии вверх (например, может понадобиться для построения списка согласующих):

-----------------------------------------------------------------
-- Список руководителей указанного работника
-----------------------------------------------------------------
with DipartmentHiererhcy (
  ID,
  HightID, 
  Level)
as
(
-- Подразделение нижнего уровня (N = 0)
  select
    department.Analit,
    department.Podr,
    0 as Level
  from
    MBAnalit department
  where
    department.Analit = 
    and department.vid = 
  union ALL
-- Ведущее подразделение (N + 1)
  select
    department.Analit,
    department.Podr,
    Level + 1
  from
    MBAnalit as department
      inner join DipartmentHiererhcy as hightdepartment
        on department.Analit = hightdepartment.HightID
  where
    department.vid = 
)
-- Список руководителей указанного работника
select distinct
  department. NameAn as [Подразделение],
  IsNull(chiefemployee.NameAn, '') as [Руководитель],
  Level as [Уровень]
from
  DipartmentHiererhcy hierarchy
    left join MBAnalit department
      on department.Analit = hierarchy.ID
    left join MBAnalit chiefemployee
      on department.FIO = chiefemployee.Analit and chiefemployee.Vid = 

В качестве P.S.

 Не стоит забывать о возможности существования бесконечной рекурсии. Во избежание используйте:

OPTION (MAXRECURSION )

 

Пример предложения WITH | sql-oracle.ru

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

Задача, демонстрируемая на рисунке, потребует следующих промежуточных вычислений:

  1. Расчет совокупного оклада для каждого отдела и сохранение результата с помощью предложения WITH.

  2. Расчет среднего оклада по отделам и сохранение результата с помощью предложения WITH.

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

Решение этой задачи показано на следующей странице.

Программный код SQL, показанный на рисунке, представляет собой пример ситуации, в которой скорость выполнения и написания SQL можно повысить более простым путем с помощью предложения WITH. Запросом создаются имена запросов DEPT_COSTS и AVG_COST, а затем они вставляются в тело главного запроса. Внутри запроса предложение WITH раскладывается как встроенное представление или временная таблица.

Оптимизатором выбирается подходящее решение в зависимости от достоинств или недостатков временного хранения результатов предложения WITH.

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

Примечания к использованию предложения WITH

  1. Используется только с инструкциями SELECT.

  2. Имя запроса отображается для всех блоков запроса элемента WITH (включая блоки их подзапросов), определенных после него и самого блока главного запроса (включая блоки его подзапросов).

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

  4. Предложение WITH может содержать более одного запроса. В этом случае каждый запрос отделяется запятой.

Далее: Примеры регулярных выражений и проверочных ограничений

SQL join в примерах с описанием

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

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

Persons (Сотрудники)

Positions (должности)

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

INNER JOIN

Внутреннее присоединение. Равносильно просто JOIN или CROSS JOIN.

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p INNER JOIN `positions` ps ON ps.id = p.post_id

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

INNER JOIN `positions` ps ON ps.id = p.post_id

Такое присоединение покажет нам данные из таблиц только если условие связывания соблюдается — т.е. для сотрудника указан существующий в словаре идентификатор должности.

Если поменять порядок соединения таблиц — получим тот же результат.

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

Далее проследим как получить разные части (подмножества) данного множества.

OUTER JOIN

Внешнее присоединение. Различают LEFT OUTER JOIN и RIGHT OUTER JOIN, и обычно опускают слово «OUTER».

Внешнее присоединение включает в себя результаты запроса INNER и добавляются «неиспользованные» строки из одной из таблиц. Какую таблицу использовать в качестве «добавки» — указывает токен LEFT или RIGHT.

LEFT JOIN

Внешнее присоединение «слева».

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id

SELECT p. id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id

«Левая» таблица persons, содержит строку id#3 — «Александр», где указан идентификатор должности, отсутствующей в словаре.

На картинке это можно показать вот так:

RIGHT JOIN

Присоединение «справа».

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id

Словарь должностей (правая таблица) содержит неиспользуемую запись с id#3 — «программист». Теперь она попала в результат запроса.

Полное множество

MySQL не знает соединения FULL OUTER JOIN. Что если нужно получить полное множество?

Первый способ — объединение запросов LEFT и RIGHT.

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id) UNION (SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id)

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id)

UNION

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

RIGHT OUTER JOIN `positions` ps ON ps. id = p.post_id)

При таком вызове UNION, после слияния результатов, SQL отсечет дубли (как DISTINCT). Для отсечения дублей SQL прибегает к сортировке. Это может сказываться на быстродействии.

Второй способ — объединение LEFT и RIGHT, но в одном из запросов мы исключаем часть, соответствующую INNER. А объединение задаём как UNION ALL, что позволяет движку SQL обойтись без сортировки.

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id) UNION ALL (SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id WHERE p.id IS NULL)

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos. id`, ps.name `Должность`

FROM `persons` p

LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id)

UNION ALL

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id

WHERE p.id IS NULL)

Этот пример показывает нам как исключить пересечение и получить только левую или правую часть множества.

Левое подмножество

LEFT JOIN ограничиваем проверкой, что данных из второй таблицы нет.

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id WHERE ps.id is NULL

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

LEFT OUTER JOIN `positions` ps ON ps. id = p.post_id

WHERE ps.id is NULL

В нашем примере — это специалисты, у которых не задана должность или нет должности с указанным ключом.

Правое подмножество

Точно также выделяем правую часть.

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id WHERE p.id is NULL

SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id

WHERE p.id is NULL

В нашем случае получим должности, которые никому не назначены.

Всё кроме пересечения

Остался один вариант, тот когда исключено пересечение множеств. Его можно сложить из двух предыдущих запросов через UNION ALL (т. к. подмножества не пересекаются).

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id WHERE ps.id is NULL) UNION ALL (SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность` FROM `persons` p RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id WHERE p.id is NULL)

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

LEFT OUTER JOIN `positions` ps ON ps.id = p.post_id

WHERE ps.id is NULL)

UNION ALL

(SELECT p.id, p.name `Имя сотрудника`, ps.id `pos.id`, ps.name `Должность`

FROM `persons` p

RIGHT OUTER JOIN `positions` ps ON ps.id = p.post_id

WHERE p.id is NULL)

Данная запись опубликована в 19. 09.2017 20:19 и размещена в mySQL. Вы можете перейти в конец страницы и оставить ваш комментарий.

Mysql select as примеры – Тарифы на сотовую связь