Error each union query must have the same number of columns

When using the UNION operator in PostgreSQL, if you encounter an error that reads “ERROR:  each UNION query must have the same number of columns“, it’s because there’s a mismatch in the number of columns returned by the queries on either side of the UNION operator.

When using the UNION operator in PostgreSQL, if you encounter an error that reads “ERROR:  each UNION query must have the same number of columns“, it’s because there’s a mismatch in the number of columns returned by the queries on either side of the UNION operator.

This error occurs when the number of columns returned by each SELECT statement is different.

The way to fix this is to ensure that both SELECT statements return the same number of columns.

Example of Error

Here’s an example of code that produces the error:

SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;

Result:

ERROR:  each UNION query must have the same number of columns
LINE 3: SELECT StudentId, StudentName FROM Students;

Here, the first SELECT statement returns one column (TeacherName), but the second SELECT statement returns two columns (StudentId and StudentName).

Solution

The solution is to ensure both SELECT statements return the same number of columns

Using the above example, we can either remove the extra column from our second SELECT statement:

SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;

Or we can add another column to the first SELECT statement:

SELECT TeacherId, TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;

It’s important to note that you can get different results depending on which option you choose. This is because UNION returns distinct rows by default. When we add another column, there’s a possibility that a previously duplicate row now becomes a unique row, depending on the value in the extra column.

We can also use UNION ALL, which returns duplicate values:

SELECT TeacherId, TeacherName FROM Teachers
UNION ALL
SELECT StudentId, StudentName FROM Students;

This can also return different results to the other examples.

Для выполнения операций над множествами все запросы должны удовлетворять следующим правилам:

  • количество полей во всех запросах должно совпадать;
  • типы данных соответствующих полей должны совпадать.

Посмотрим, что это значит на практике. Таблицы для примеров:

SELECT *
  FROM table1
SELECT *
  FROM table2

Что будет, если количество столбцов в запросах не будет совпадать?

SELECT value, name
  FROM table1
 UNION
SELECT value
  FROM table1
each UNION query must have the same number of columns

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

SELECT value
  FROM table1
 UNION
SELECT name
  FROM table1
UNION types integer and text cannot be matched

Что делать, если очень хочется объединить столбцы с разными типами данных? Нужно их преобразовать к одному типу данных. Функции преобразования типов данных рассмотрим в отдельной теме, а пока преобразуем столбец value к строке:

SELECT value::text
  FROM table1
 UNION
SELECT name
  FROM table1

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

Если хочешь знать точные правила определения типа данных столбца, то можешь найти их здесь

Introduction

In this article we will discuss the UNION and UNION ALL operators in PostgreSQL database. These two operators are both used combine results from different tables. It’s rare that you’ll develop an application without ever having to create queries that combine result sets from multiple tables. Unions come from set theory. In set theory there is an operation called Union that combines two different or same sets and gives a unique third set as a solution. How union works in set is as follows:

Consider the set A and B as in figure below the union of these two sets will be all the values of set A and all the values of set B except for duplicates i.e. those same values that are in both A and B will be included only once.

Image from Gyazo

So, let’s consider the Example of Set A and B to be:
A = {1,2,3,4}
B = {2,4,5,6}
So, A U B will be {1,2,3,4,5,6}.

This was the Union operator in Set theory. Now let’s see how PostgreSQL provides that functionality.

Union in PostgreSQL

In PostgreSQL this facility to merge two different or same tables similar to the two sets A and B is the UNION operator. In PostgreSQL UNION operator is used to combine two SELECT statements. The syntax is as follows:

1
2
3
4
5
6
7

SELECT [column1…columnN]
FROM table_1
[WHERE conditions]
UNION
SELECT [column1…columnN]
FROM table_2
[WHERE conditions]

Let’s use UNION in an example. Consider Two tables named as SalesA and SalesB respectively. The data in Both tables is shown below. Both tables have same columns but different data rows:

salesa:

1
2
3
4
5
6

  name  | numsales
———+———-
 Henry  |       50
 Edward |       60
 Sheila |      100
(3 rows)

salesb:

1
2
3
4
5
6

  name  | numsales
———+———-
 Henry  |       50
 Edward |       60
 Sheila |       99
(3 rows)

Now the SQL statement for UNION of these two tables will be:

1
2
3

SELECT * FROM salesa
UNION
SELECT * FROM salesb

The result will be a new table with merged data rows from both tables

1
2
3
4
5
6
7

  name  | numsales
———+———-
 Henry  |       50
 Edward |       60
 Sheila |       99
 Sheila |      100
(4 rows)

There are four rows in the combined result set because the UNION operator removes two duplicate rows. As you may have noticed in the above example the columns in both tables were the same. PostgreSQL has some special rules for UNION operator to work:
1. Each SELECT statement in the UNION query should have same number of columns.
2. The columns must also have similar data types.
3. The columns in each SELECT statement must also be in same order.

Let’s see how these rules effect the UNION statement.

First Rule:
Let’s examine the first rule and see what happens when we violate it with a union like this:

1
2
3

SELECT name, numsales from salesa
UNION
SELECT name from salesb;

Result:

1
2

ERROR:  each UNION query must have the same number of columns
LINE 3: SELECT name from salesb;

This time we selected name and amount from salesa and only name from salesb and because this violates rule 1 so PostgreSQL gives and error stating “Each UNION query must have same number of columns”.

Second Rule:
To check the second rules let’s create a new table salesc with numsales as a text type.

1

CREATE TABLE salesc (name VARCHAR (50), numsales VARCHAR (50));

Now if we take the union of salesa and saless it will give an error because salesa amount column is in integer and salesc amount column is in Text.

1
2
3

SELECT numsales from salesa
UNION
SELECT numsales from salesc;

Returns:

1
2

ERROR:  UNION types integer and character varying cannot be matched
LINE 3: SELECT numsales from salesc

Third Rule:
This rule is simple. In order to visualize lets again take example of salesa and salesb but this time we will change the order of the columns in the select statements. We will take numsales first and name as second column in salesa and vice versa in salesb.

1
2
3

SELECT numsales, name from salesa
UNION
SELECT name, numsales from salesb;

Returns:

1
2

ERROR:  UNION types integer and character varying cannot be matched
LINE 3: SELECT name, numsales from salesb;

It gave the same error as in second rules because the query tried to match the name column with account column which was wrong.

Union All in PostgreSQL

In previous we saw how the UNION operator works in PostgreSQL. There is another operator in PostgreSQL that works similar to UNION operator and that is UNION ALL. UNION ALL works just like UNION with the same conditions that UNION had i.e. the three previously defined rules the only difference is that UNION removes duplicate rows but UNION ALL does not remove duplicate rows. UNION ALL just merges all the rows that satisfy all the conditions. In order to understand it lets consider the same sales tables example. This time we will use UNION ALL operator to see the difference.

We start with these two tables.

Table salesa:

1
2
3
4
5
6

  name  | numsales
———+———-
 Henry  |       50
 Edward |       60
 Sheila |      100
(3 rows)

Table salesb:

1
2
3
4
5
6

  name  | numsales
———+———-
 Henry  |       50
 Edward |       60
 Sheila |       99
(3 rows)

Notice that there are two rows that are same in both tables i.e. (Henry, 50) and (Edward, 60).

Now if we use UNION ALL on this table:

1
2
3

SELECT * FROM salesa
UNION ALL
SELECT * FROM salesb;

The result set is:

1
2
3
4
5
6
7
8
9

  name  | numsales
———+———-
 Henry  |       50
 Edward |       60
 Sheila |      100
 Henry  |       50
 Edward |       60
 Sheila |       99
(6 rows)

Notice the result set included all the rows even the duplicate ones.

All other things about UNION ALL and UNION are the same but here comes the question why UNION ALL exists when there is UNION that does all things. So, the answer to that question is performance efficiency.

Performance is another difference between UNION ALL and UNION. UNION ALL is faster than UNION as it does not remove the duplicates so when there is performance constraint, we will use UNION ALL because in performance issues we usually want to just analyze the data set. Let’s see an example as follows.

Performance of UNION:

1

SELECT ‘foo’ AS bar UNION SELECT ‘foo’ AS bar

Result:

1
2
3
4
5
6

+——+
| bar |
+——+
| foo |
+——+
1 row in set (0.01 sec)

Performance of UNION ALL:

1

SELECT ‘foo’ AS bar UNION ALL SELECT ‘foo’ AS bar

Result:

1
2
3
4
5
6
7

+——+
| bar |
+——+
| foo |
| foo |
+——+
2 rows in set (0.00 sec)

Order

Note that on UNION and UNION ALL merge the rows in a non-specific order so in order to avoid such scenario, use the PostgreSQL ORDER BY command.

Conclusion

Both UNION and UNION ALL are used for merging the rows of two SELECT statements. The difference is that UNION removes duplicates whereas UNION ALL does not which results in slower performance.

   andrejip

26.11.10 — 15:49

Добрый вечер всем!

1С УПП 8.2 (8.2.12.87) ред. 1.3 (1.3.6.1).

Крутится на PostgreSQL

Когда делаю реализациюТоваровИУслуг и в колонке СпособСписания указываю ИЗ РЕЗЕРВА, вылетает ошибка:

http://narod.ru/disk/375673001/снимок1.png.html

и 1С-ка вылетает. Подскажите как исправить ошибку и в чем дело.

   andrejip

1 — 26.11.10 — 15:51

уточнение: указываю ИЗ РЕЗЕРВА, нажимаю ОК (записать и провести) и тогда вылетает ошибка.

   Живой Ископаемый

2 — 26.11.10 — 15:51

а если например скажут, что для того чтобы исправить ошибку, нужно сменить сервер БД… сделаешь?

   andrejip

3 — 26.11.10 — 15:53

Текст ошибки кто не может просмотреть скрин:

Ошибка СУБД ERROR: each UNION query must have the same number of columns at character 4478

   andrejip

4 — 26.11.10 — 15:54

(2) Что значит сменить? :) В переставить :)

Подскажи если знаешьсчитаешь из-за чего может быть ошибка,, и как исправить.

   andrejip

5 — 26.11.10 — 15:58

(2) :) вопрос не в том смогу или не смогу. вопрос я написал.

   andrejip

6 — 26.11.10 — 15:58

up

   Живой Ископаемый

7 — 26.11.10 — 15:59

2(4) Сменить — это значит воспользоваться любым другим из еще 3-х возможных…
Например МС СКЛ, ДБ2, Оракл…

ошибка из-за того что движек транслирует 1Совский запрос в СКЛ-запрос такой, который Постгрес считает некорректным. Выходов как обычно три — скорректировать запрос(сделав его нетиповым), попробовав и выбрав другой сервер, если совсем клевый дядька — то уже почесать сам постгрес, вдруг как-то можно сделать чтобы он считал этот запрос годным

   Живой Ископаемый

8 — 26.11.10 — 16:00

2(5) вопрос ты не написал — в тексте нет ни одного вопросительного знака.. стало быть что именно считать вопросом читатели твоего поста могут сами.
Я интерпретирую вопрос так, что нужно проблему решить, то есть реализацию провести сейчас и в дальнейшем

   andrejip

9 — 26.11.10 — 16:01

(7) неплохо ответил. Буду пробовать.

У кого ещё если мысли пишите. Как исправлю напишу как.

   andrejip

10 — 26.11.10 — 16:02

(8) ? ок.

   Живой Ископаемый

11 — 26.11.10 — 16:04

Если интересует как именно получить текст запроса который Постгрес посчитал негодным,могу подсказать что нужно настроить Технологический Журнал

   andrejip

12 — 26.11.10 — 16:08

:) СП.

   Живой Ископаемый

13 — 26.11.10 — 16:10

   andrejip

14 — 26.11.10 — 16:19

(13) :) ещё СП.

   andrejip

15 — 29.11.10 — 09:36

//в продолжении темы.

Лог полученного файла:

19:56.2210-0,EXCP,5,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.,Exception=DataBaseException,Descr=’Ошибка СУБД:
ERROR:  each UNION query must have the same number of columns at character 4526
‘,Context=’
ОбщийМодуль.ПроцедурыКонтроляОстатков.Модуль : 4235 : ТоварыВРезервеНаСкладахКонтрольОстатков_Реализация(СтруктураШапкиДокумента, СтруктураПараметров, Заголовок, Отказ);
   ОбщийМодуль.ПроцедурыКонтроляОстатков.Модуль : 4599 : РезультатЗапроса = Запрос.Выполнить();’
19:56.2211-0,EXCPCNTX,0,ClientComputerName=ois2,ServerComputerName=serv_1c,UserName=Калошин А.Г.,ConnectString=’Srvr=»serv_1c»;Ref=»test»;’
19:56.2212-97,EXCPCNTX,4,SrcName=DBPOSTGRS,OSThread=-471500528,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.,Trans=1,dbpid=13446,Sql=»SELECT
T1.Q_001_F_001RRef,
T14._IDRRef,
T14._Description,
T15._IDRRef,
T15._Description,
T1.Q_001_F_004RRef,
T1.Q_001_F_004RRef,
T16._Description,
‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea,
‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea,
T17._Description,
T1.Q_001_F_007RRef,
T1.Q_001_F_002RRef,
SUM(CAST((CAST(CAST((T1.Q_001_F_009_ * T1.Q_001_F_006_) AS NUMERIC(38, 8)) / T15._Fld1656 AS NUMERIC(38, 8))) AS NUMERIC(15, 3))),
COALESCE(CAST(MAX(T8.Fld21406Balance_) AS NUMERIC(27, 3)),0)
FROM (SELECT
T2._Document481_IDRRef AS Q_001_F_000RRef,
T2._Fld13110RRef AS Q_001_F_001RRef,
T2._Fld13120RRef AS Q_001_F_002RRef,
T2._Fld13121RRef AS Q_001_F_003RRef,
T2._Fld13134RRef AS Q_001_F_004RRef,
T2._Fld13119RRef AS Q_001_F_005RRef,
T2._Fld13109 AS Q_001_F_006_,
T2._Fld13136RRef AS Q_001_F_007RRef,
T2._Fld13103RRef AS Q_001_F_008RRef,
CAST(T2._Fld13107 AS NUMERIC(30, 6)) AS Q_001_F_009_
FROM _Document481_VT13101 T2
LEFT OUTER JOIN _Reference126 T3
ON T2._Fld13110RRef = T3._IDRRef
WHERE (T2._Document481_IDRRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea) AND (T3._Fld2122 = FALSE) AND (T2._Fld13121RRef = ‘\272\203\025\316gs\007JC\334\3130BL\3315’::bytea)
UNION ALL SELECT
T4.Q_002_F_000RRef AS Q_002_F_000RRef,
T4.Q_002_F_001RRef AS Q_002_F_001RRef,
T4.Q_002_F_002RRef AS Q_002_F_002RRef,
T4.Q_002_F_003RRef AS Q_002_F_003RRef,
T4.Q_002_F_004RRef AS Q_002_F_004RRef,
T4.Q_002_F_005RRef AS Q_002_F_005RRef,
T4.Q_002_F_006_ AS Q_002_F_006_,
T4.Q_002_F_007RRef AS Q_002_F_007RRef,
T4.Q_002_F_008RRef AS Q_002_F_008RRef,
T4.Q_002_F_009_ AS Q_002_F_009_
FROM (SELECT
T5._Document481_IDRRef AS Q_002_F_000RRef,
T5._Fld13182RRef AS Q_002_F_001RRef,
CASE WHEN (T5._Fld13187RRef = ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea) THEN T6._Fld13120RRef ELSE T5._Fld13187RRef END AS Q_002_F_002RRef,
CASE WHEN (T5._Fld13189RRef = ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea) THEN T6._Fld13121RRef ELSE T5._Fld13189RRef END AS Q_002_F_003RRef,
T5._Fld13183RRef AS Q_002_F_004RRef,
T5._Fld13184RRef AS Q_002_F_005RRef,
T7._Fld1656 AS Q_002_F_006_,
T6._Fld13136RRef AS Q_002_F_007RRef,
T6._Fld13103RRef AS Q_002_F_008RRef,
(T5._Fld13185 * T6._Fld13107) AS Q_002_F_009_
FROM _Document481_VT13180 T5
LEFT OUTER JOIN _Document481_VT13101 T6
ON ((T6._Fld13138 = T5._Fld13190) AND (T6._Document481_IDRRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea))
LEFT OUTER JOIN _Reference78 T7
ON T5._Fld13186RRef = T7._IDRRef
WHERE (T5._Document481_IDRRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea)) T4
WHERE (T4.Q_002_F_003RRef = ‘\272\203\025\316gs\007JC\334\3130BL\3315’::bytea)) T1
LEFT OUTER JOIN (SELECT
T9._Fld21401RRef AS Fld21401RRef,
T9._Fld21402RRef AS Fld21402RRef,
T9._Fld21403RRef AS Fld21403RRef,
T9._Fld21404_TYPE AS Fld21404_TYPE,
T9._Fld21404_RTRef AS Fld21404_RTRef,
T9._Fld21404_RRRef AS Fld21404_RRRef,
T9._Fld21405RRef AS Fld21405RRef,
SUM(T9._Fld21406) AS Fld21406Balance_
FROM _AccumRgT21409 T9
WHERE T9._Period = ‘3999-11-01 00:00:00’::timestamp AND (((T9._Fld21403RRef = ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea) AND (T9._Fld21402RRef, T9._Fld21401RRef, CASE WHEN T9._Fld21404_TYPE IN (‘\001’::bytea, ‘\010’::bytea) THEN T9._Fld21404_TYPE END, CASE WHEN T9._Fld21404_TYPE = ‘\010’::bytea THEN T9._Fld21404_RTRef WHEN T9._Fld21404_TYPE IN (‘\001’::bytea) THEN ‘\000\000\000\000’::bytea END, CASE WHEN T9._Fld21404_TYPE = ‘\010’::bytea THEN T9._Fld21404_RRRef WHEN T9._Fld21404_TYPE IN (‘\001’::bytea, ‘\010’::bytea) THEN ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea END) IN
(SELECT
T10._Fld13110RRef AS Q_004_F_000RRef,
T10._Fld13120RRef AS Q_004_F_001RRef,
‘\010’::bytea AS Q_004_F_002_TYPE,
‘\000\000\001/’::bytea AS Q_004_F_002_RTRef,
T10._Fld13136RRef AS Q_004_F_002_RRRef
FROM _Document481_VT13101 T10
LEFT OUTER JOIN _Reference126 T11
ON T10._Fld13110RRef = T11._IDRRef
WHERE (T10._Document481_IDRRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea) AND (T11._Fld2122 = FALSE) AND (T10._Fld13121RRef = ‘\272\203\025\316gs\007JC\334\3130BL\3315’::bytea) AND (NOT (((T10._Fld13136RRef IN (‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea)))))
UNION ALL SELECT
T12._Fld13182RRef AS Fld13182RRef,
CASE WHEN (T12._Fld13187RRef = ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea) THEN T13._Fld13120RRef ELSE T12._Fld13187RRef END,
T13._Fld13136RRef AS Fld13136RRef
FROM _Document481_VT13180 T12
LEFT OUTER JOIN _Document481_VT13101 T13
ON ((T13._Fld13138 = T12._Fld13190) AND (T13._Document481_IDRRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea))
WHERE (T12._Document481_IDRRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea))))
GROUP BY T9._Fld21401RRef,
T9._Fld21402RRef,
T9._Fld21403RRef,
T9._Fld21404_TYPE,
T9._Fld21404_RTRef,
T9._Fld21404_RRRef,
T9._Fld21405RRef
HAVING (SUM(T9._Fld21406)) <> 0) T8
ON (((((T8.Fld21401RRef = T1.Q_001_F_002RRef) AND (T8.Fld21402RRef = T1.Q_001_F_001RRef)) AND (T8.Fld21404_TYPE = CASE WHEN T1.Q_001_F_007RRef IS NOT NULL THEN ‘\010’::bytea END AND T8.Fld21404_RTRef = CASE WHEN T1.Q_001_F_007RRef IS NOT NULL THEN ‘\000\000\001/’::bytea END AND T8.Fld21404_RRRef = T1.Q_001_F_007RRef)) AND (T8.Fld21403RRef = ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea)) AND (T8.Fld21405RRef = ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea))
LEFT OUTER JOIN _Reference126 T14
ON T1.Q_001_F_001RRef = T14._IDRRef
LEFT OUTER JOIN _Reference78 T15
ON T14._Fld2104RRef = T15._IDRRef
LEFT OUTER JOIN _Reference235 T16
ON T1.Q_001_F_004RRef = T16._IDRRef
LEFT OUTER JOIN _Reference179 T17
ON ‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea = T17._IDRRef
WHERE (T14._Fld2122 = FALSE) AND (T1.Q_001_F_000RRef = ‘:\237H[9H\302\215\021\337\373\200\256\356\260\302’::bytea) AND (T1.Q_001_F_003RRef = ‘\272\203\025\316gs\007JC\334\3130BL\3315’::bytea) AND (NOT (((T1.Q_001_F_007RRef IN (‘\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000’::bytea)))))
GROUP BY T1.Q_001_F_001RRef,
T1.Q_001_F_004RRef,
T1.Q_001_F_007RRef,
T1.Q_001_F_002RRef,
T14._IDRRef,
T14._Description,
T15._IDRRef,
T15._Description,
T1.Q_001_F_004RRef,
T16._Description,
T17._Description
HAVING (COALESCE(CAST(MAX(T8.Fld21406Balance_) AS NUMERIC(27, 3)),0) < SUM(CAST((CAST(CAST((T1.Q_001_F_009_ * T1.Q_001_F_006_) AS NUMERIC(38, 8)) / T15._Fld1656 AS NUMERIC(38, 8))) AS NUMERIC(15, 3))))»,Result=PGRES_FATAL_ERROR,dbpid=13446,Sql=ROLLBACK,Result=PGRES_COMMAND_OK
19:56.2213-99,EXCPCNTX,3,SrcName=SDBL,OSThread=-471500528,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.,Trans=1,Sdbl=’SELECT
Q_000_T_001.Q_001_F_001,
CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).ID, CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Description,
CAST(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2104 AS REF(Reference78)).ID, CAST(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2104 AS REF(Reference78)).Description,
Q_000_T_001.Q_001_F_004,
CAST(Q_000_T_001.Q_001_F_004 AS REF(Reference235)), CAST(CAST(Q_000_T_001.Q_001_F_004 AS REF(Reference235)) AS REF(Reference235)).Description,
179:00000000000000000000000000000000,
CAST(179:00000000000000000000000000000000 AS REF(Reference179)), CAST(CAST(179:00000000000000000000000000000000 AS REF(Reference179)) AS REF(Reference179)).Description,
Q_000_T_001.Q_001_F_007,
Q_000_T_001.Q_001_F_002,
SUM(CAST(((Q_000_T_001.Q_001_F_009 * Q_000_T_001.Q_001_F_006) / CAST(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2104 AS REF(Reference78)).Fld1656) AS NUMERIC(15, 3))),
ISNULL(MAX(Q_000_T_002.Fld21406Balance), 0)
FROM
(SELECT
Q_001_T_001.ID Q_001_F_000,
Q_001_T_001.Fld13110 Q_001_F_001,
Q_001_T_001.Fld13120 Q_001_F_002,
Q_001_T_001.Fld13121 Q_001_F_003,
Q_001_T_001.Fld13134 Q_001_F_004,
Q_001_T_001.Fld13119 Q_001_F_005,
Q_001_T_001.Fld13109 Q_001_F_006,
Q_001_T_001.Fld13136 Q_001_F_007,
Q_001_T_001.Fld13103 Q_001_F_008,
Q_001_T_001.Fld13107 Q_001_F_009
FROM
Document481.VT13101 Q_001_T_001
WHERE
(Q_001_T_001.ID = 481:3a9f485b3948c28d11dffb80aeeeb0c2) AND (NOT(CAST(Q_001_T_001.Fld13110 AS REF(Reference126)).Fld2122)) AND (Q_001_T_001.Fld13121 = 932:ba8315ce6773074a43dccb30424cd935)
UNION ALL
SELECT
Q_003_T_001.Q_002_F_000,
Q_003_T_001.Q_002_F_001,
Q_003_T_001.Q_002_F_002,
Q_003_T_001.Q_002_F_003,
Q_003_T_001.Q_002_F_004,
Q_003_T_001.Q_002_F_005,
Q_003_T_001.Q_002_F_006,
Q_003_T_001.Q_002_F_007,
Q_003_T_001.Q_002_F_008,
Q_003_T_001.Q_002_F_009
FROM
(SELECT
Q_002_T_001.ID Q_002_F_000,
Q_002_T_001.Fld13182 Q_002_F_001,
CASE  WHEN (Q_002_T_001.Fld13187 = 181:00000000000000000000000000000000) THEN Q_002_T_002.Fld13120 ELSE Q_002_T_001.Fld13187 END  Q_002_F_002,
CASE  WHEN (Q_002_T_001.Fld13189 = 932:00000000000000000000000000000000) THEN Q_002_T_002.Fld13121 ELSE Q_002_T_001.Fld13189 END  Q_002_F_003,
Q_002_T_001.Fld13183 Q_002_F_004,
Q_002_T_001.Fld13184 Q_002_F_005,
CAST(Q_002_T_001.Fld13186 AS REF(Reference78)).Fld1656 Q_002_F_006,
Q_002_T_002.Fld13136 Q_002_F_007,
Q_002_T_002.Fld13103 Q_002_F_008,
(Q_002_T_001.Fld13185 * Q_002_T_002.Fld13107) Q_002_F_009
FROM
Document481.VT13180 Q_002_T_001 LEFT JOIN Document481.VT13101 Q_002_T_002 ON ((Q_002_T_002.Fld13138 = Q_002_T_001.Fld13190) AND (Q_002_T_002.ID = 481:3a9f485b3948c28d11dffb80aeeeb0c2))
WHERE
(Q_002_T_001.ID = 481:3a9f485b3948c28d11dffb80aeeeb0c2)
) Q_003_T_001
WHERE
(Q_003_T_001.Q_002_F_003 = 932:ba8315ce6773074a43dccb30424cd935)

) Q_000_T_001 LEFT JOIN (SELECT Fld21401, Fld21402, Fld21403, Fld21404, Fld21405, SUM(Fld21406) AS Fld21406Balance FROM AccumRgT21409 WHERE Period = DATETIME(3999,11,1) AND (((Fld21403 = 235:00000000000000000000000000000000) AND (Fld21402, Fld21401, Fld21404) IN (SELECT
Q_004_T_001.Fld13110 Q_004_F_000,
Q_004_T_001.Fld13120 Q_004_F_001,
Q_004_T_001.Fld13136 Q_004_F_002
FROM
Document481.VT13101 Q_004_T_001
WHERE
(Q_004_T_001.ID = 481:3a9f485b3948c28d11dffb80aeeeb0c2) AND (NOT(CAST(Q_004_T_001.Fld13110 AS REF(Reference126)).Fld2122)) AND (Q_004_T_001.Fld13121 = 932:ba8315ce6773074a43dccb30424cd935) AND (NOT(Q_004_T_001.Fld13136 IN (UNDEFINED, 303:00000000000000000000000000000000)))
UNION ALL
SELECT
Q_005_T_001.Fld13182,
CASE  WHEN (Q_005_T_001.Fld13187 = 181:00000000000000000000000000000000) THEN Q_005_T_002.Fld13120 ELSE Q_005_T_001.Fld13187 END ,
Q_005_T_002.Fld13136
FROM
Document481.VT13180 Q_005_T_001 LEFT JOIN Document481.VT13101 Q_005_T_002 ON ((Q_005_T_002.Fld13138 = Q_005_T_001.Fld13190) AND (Q_005_T_002.ID = 481:3a9f485b3948c28d11dffb80aeeeb0c2))
WHERE
(Q_005_T_001.ID = 481:3a9f485b3948c28d11dffb80aeeeb0c2)

))) GROUP BY Fld21401, Fld21402, Fld21403, Fld21404, Fld21405 HAVING Fld21406Balance <> 0 FOR UPDATE) Q_000_T_002 ON (((((Q_000_T_002.Fld21401 = Q_000_T_001.Q_001_F_002) AND (Q_000_T_002.Fld21402 = Q_000_T_001.Q_001_F_001)) AND (Q_000_T_002.Fld21404 = Q_000_T_001.Q_001_F_007)) AND (Q_000_T_002.Fld21403 = 235:00000000000000000000000000000000)) AND (Q_000_T_002.Fld21405 = 179:00000000000000000000000000000000))
WHERE
(NOT(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2122)) AND (Q_000_T_001.Q_001_F_000 = 481:3a9f485b3948c28d11dffb80aeeeb0c2) AND (Q_000_T_001.Q_001_F_003 = 932:ba8315ce6773074a43dccb30424cd935) AND (NOT(Q_000_T_001.Q_001_F_007 IN (UNDEFINED, 303:00000000000000000000000000000000)))
GROUP BY
Q_000_T_001.Q_001_F_001,
Q_000_T_001.Q_001_F_004,
179:00000000000000000000000000000000,
Q_000_T_001.Q_001_F_007,
Q_000_T_001.Q_001_F_002,
CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).ID, CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Description,
CAST(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2104 AS REF(Reference78)).ID, CAST(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2104 AS REF(Reference78)).Description,
CAST(Q_000_T_001.Q_001_F_004 AS REF(Reference235)), CAST(CAST(Q_000_T_001.Q_001_F_004 AS REF(Reference235)) AS REF(Reference235)).Description,
CAST(179:00000000000000000000000000000000 AS REF(Reference179)), CAST(CAST(179:00000000000000000000000000000000 AS REF(Reference179)) AS REF(Reference179)).Description
HAVING
(ISNULL(MAX(Q_000_T_002.Fld21406Balance), 0) < SUM(CAST(((Q_000_T_001.Q_001_F_009 * Q_000_T_001.Q_001_F_006) / CAST(CAST(Q_000_T_001.Q_001_F_001 AS REF(Reference126)).Fld2104 AS REF(Reference78)).Fld1656) AS NUMERIC(15, 3))))

19:56.2214-259,EXCPCNTX,2,SrcName=CALL,OSThread=-471500528,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.
19:56.2215-9103,EXCPCNTX,2,SrcName=SDBL,OSThread=-471500528,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.,Trans=0,Func=Transaction
19:56.2216-9105,EXCPCNTX,1,SrcName=SDBL,OSThread=-471500528,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.,Trans=0,Func=HoldConnection
19:56.2311-0,Context,2,process=rphost,p:processName=test,t:clientID=111,t:applicationName=1CV8,t:computerName=ois2,t:connectID=88,SessionID=70,Usr=Калошин А.Г.,Context=’
{Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента}/{КоманднаяПанель : ОсновныеДействияФормы}/{ОК}
Документ.РеализацияТоваровУслуг.МодульОбъекта : 5119 : ДвиженияПоРегистрам(РежимПроведения, СтруктураШапкиДокумента, ТаблицаПоТоварам, ТаблицаПоСкидкам, ТаблицаПоТаре,
   Документ.РеализацияТоваровУслуг.МодульОбъекта : 3362 : ДвиженияПоРегистрамУпр(РежимПроведения, СтруктураШапкиДокумента,
       Документ.РеализацияТоваровУслуг.МодульОбъекта : 3719 : ПроцедурыКонтроляОстатков.ТоварыВРезервеНаСкладахКонтрольОстатков(«Товары», СтруктураШапкиДокумента, Отказ, Заголовок, РежимПроведения);’
21:21.5550-0,EXCP,0,process=rphost,Exception=LoadComponent(sqlsrvr),Descr=Error loading component sqlsrvr
23:33.0720-0,EXCP,0,process=rphost,Exception=LoadComponent(sqlsrvr),Descr=Error loading component sqlsrvr
23:33.5320-0,EXCP,0,process=rphost,Exception=LoadComponent(sqlsrvr),Descr=Error loading component sqlsrvr
23:33.9820-0,EXCP,0,process=rphost,Exception=LoadComponent(sqlsrvr),Descr=Error loading component sqlsrvr
25:58.5890-0,EXCP,0,process=rphost,Exception=LoadComponent(sqlsrvr),Descr=Error loading component sqlsrvr
25:59.0490-0,EXCP,0,process=rphost,Exception=LoadComponent(sqlsrvr),Descr=Error loading component sqlsrvr

   andrejip

16 — 29.11.10 — 09:37

Вопрос: можно ли (как) не меняя БД к-либо исправить ошибку, кто подсобит мнением?

   andrejip

17 — 29.11.10 — 09:43

up

   andrejip

18 — 29.11.10 — 10:13

ап

   andrejip

19 — 29.11.10 — 10:18

е

   73

20 — 29.11.10 — 10:19

Для полноты картинки:
версия PostgreSQL ?
патчена?

   diger

21 — 29.11.10 — 10:19

Если сервер 1с на Линуксе крутится, то попробовать связку
сервер 1с на винде, а постгрес на линуксе оставить…

   andrejip

22 — 29.11.10 — 11:00

секунду..

   andrejip

23 — 29.11.10 — 11:03

(20) патчена последняя версия..

   Живой Ископаемый

24 — 29.11.10 — 11:08

А как выглядит 1С-овский запрос?

   andrejip

25 — 29.11.10 — 11:17

(20) 8.4.1 еще есть 8.4.3.. попробую поставить

   73

26 — 29.11.10 — 11:18

(25) Обычно помогает установка дистрибутива и патчей именно от 1С…

   andrejip

27 — 29.11.10 — 11:21

(24) ОбщиеМодули.ПроцедурыКонтроляОстатков.ТоварыНаСкладахКонтрольОстатков.

   andrejip

28 — 29.11.10 — 11:21

Процедура ТоварыНаСкладахКонтрольОстатков(ИмяТабличнойЧасти, СтруктураШапкиДокумента, ОтказПроведения, ЗаголовокСообщения, РежимПроведения) Экспорт

       Если РежимПроведения <> РежимПроведенияДокумента.Оперативный Тогда
       Возврат;
   КонецЕсли;

       Если УправлениеДопПравамиПользователей.РазрешеноПревышениеОстаткаТоваровНаСкладе() Тогда
       Возврат;
   КонецЕсли;

       Если глЗначениеПеременной(«ИспользоватьРегистрСвободныеОстатки») Тогда
       СвободныеОстаткиКонтрольОстатков(ИмяТабличнойЧасти, СтруктураШапкиДокумента, ОтказПроведения, ЗаголовокСообщения);
       Возврат;
   КонецЕсли;

       ИспользоватьУказаниеСерийНоменклатурыПриРезервировании = Ложь;
   Если НЕ СтруктураШапкиДокумента.Свойство(«ИспользоватьУказаниеСерийНоменклатурыПриРезервировании», ИспользоватьУказаниеСерийНоменклатурыПриРезервировании) Тогда
       ИспользоватьУказаниеСерийНоменклатурыПриРезервировании = глЗначениеПеременной(«ИспользоватьУказаниеСерийНоменклатурыПриРезервировании»);
   КонецЕсли;

       ИспользоватьХарактеристикиНоменклатуры = глЗначениеПеременной(«ИспользоватьХарактеристикиНоменклатуры»);
   ИспользоватьСерииНоменклатуры = глЗначениеПеременной(«ИспользоватьСерииНоменклатуры»);

       Отказ     = ОтказПроведения;
   Заголовок = ЗаголовокСообщения;

   МетаданныеДокумента = СтруктураШапкиДокумента.Ссылка.Метаданные();
   ИмяДокумента        = МетаданныеДокумента.Имя;
   ИмяТаблицы          = ИмяДокумента + «.» + СокрЛП(ИмяТабличнойЧасти);
   Если ИмяТабличнойЧасти <> «» Тогда
       МетаданныеТабЧасти = МетаданныеДокумента.ТабличныеЧасти[ИмяТабличнойЧасти];
   КонецЕсли;

   СтруктураПараметров = Новый Структура;
   СтруктураПараметров.Вставить(«МетаданныеДокумента»,    МетаданныеДокумента);
   СтруктураПараметров.Вставить(«ИмяДокумента»,        ИмяДокумента);
   СтруктураПараметров.Вставить(«ИмяТабличнойЧасти»,    ИмяТабличнойЧасти);
   СтруктураПараметров.Вставить(«ИмяТаблицы»,            ИмяТаблицы);

       СтруктураПараметров.Вставить(«ИспользоватьУказаниеСерийНоменклатурыПриРезервировании»,    ИспользоватьУказаниеСерийНоменклатурыПриРезервировании);
   СтруктураПараметров.Вставить(«ИспользоватьХарактеристикиНоменклатуры»,                    ИспользоватьХарактеристикиНоменклатуры);
   СтруктураПараметров.Вставить(«ИспользоватьСерииНоменклатуры»,                            ИспользоватьСерииНоменклатуры);

       СтруктураПараметров.Вставить(«РегистрОстаткиТоваров», «ТоварыНаСкладах»);

       Если СтруктураПараметров.ИмяДокумента = «ПеремещениеТоваров» Тогда

               ТоварыНаСкладахКонтрольОстатков_ПеремещениеТоваров(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);

           ИначеЕсли СтруктураПараметров.ИмяДокумента = «РеализацияТоваровУслуг» Тогда

               Если СтруктураПараметров.ИмяТабличнойЧасти = «ВозвратнаяТара» Тогда
           ТоварыНаСкладахКонтрольОстатков_ЗаказВТабЧасти(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);
       Иначе    
           ТоварыНаСкладахКонтрольОстатков_Реализация_ОтчетОРознПродажах_ЧекККМ(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);
       КонецЕсли;

   ИначеЕсли СтруктураПараметров.ИмяДокумента = «ОтчетОРозничныхПродажах»
       ИЛИ СтруктураПараметров.ИмяДокумента = «ЧекККМ» Тогда

               ТоварыНаСкладахКонтрольОстатков_Реализация_ОтчетОРознПродажах_ЧекККМ(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);

           ИначеЕсли СтруктураПараметров.ИмяДокумента = «ВозвратТоваровПоставщику» Тогда

               Если СтруктураШапкиДокумента.ВидОперации = Перечисления.ВидыОперацийВозвратТоваровПоставщику.ИзПереработки Тогда
           ТоварыНаСкладахКонтрольОстатков_СкладВТабЧасти_ЗаказВШапке(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);
       ИначеЕсли СтруктураПараметров.ИмяТабличнойЧасти = «Оборудование» Тогда
           ТоварыНаСкладахКонтрольОстатков_БезЗаказа(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);
       Иначе
           ТоварыНаСкладахКонтрольОстатков_ЗаказВТабЧасти(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);
       КонецЕсли;

           ИначеЕсли СтруктураПараметров.ИмяДокумента = «ТребованиеНакладная»
       ИЛИ СтруктураПараметров.ИмяДокумента = «РасходныйОрдерНаТовары»
       ИЛИ СтруктураПараметров.ИмяДокумента = «СписаниеТоваров» Тогда

                       ТоварыНаСкладахКонтрольОстатков_ЗаказВТабЧасти(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);

           ИначеЕсли СтруктураПараметров.ИмяДокумента = «ПередачаТоваров» Тогда

               ТоварыНаСкладахКонтрольОстатков_СкладВШапке_ЗаказВШапке(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);

           ИначеЕсли СтруктураПараметров.ИмяДокумента = «КомплектацияНоменклатуры» Тогда
       Если СтруктураШапкиДокумента.ВидКомплектации = Перечисления.ВидыКомплектации.Разборка Тогда
           //при разукомплектации все берем из шапки
           СтруктураПараметров.ИмяТаблицы = СтруктураПараметров.ИмяДокумента;
       КонецЕсли;

               ТоварыНаСкладахКонтрольОстатков_СкладВШапке_ЗаказВШапке(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);

           ИначеЕсли СтруктураПараметров.ИмяДокумента = «ПередачаМатериаловВЭксплуатацию»
       ИЛИ СтруктураПараметров.ИмяДокумента = «ПередачаОборудованияВМонтаж»
       ИЛИ    СтруктураПараметров.ИмяДокумента = «КорректировкаСерийИХарактеристикТоваров»
       ИЛИ СтруктураПараметров.ИмяДокумента = «КорректировкаКачестваТоваров» Тогда

               ТоварыНаСкладахКонтрольОстатков_БезЗаказа(СтруктураШапкиДокумента, СтруктураПараметров, МетаданныеТабЧасти, Заголовок, Отказ);

           Иначе

               Сообщить(«Для документа вида «»» + СтруктураПараметров.ИмяДокумента + «»» не предусмотрен вызов процедуры контроля остатков (процедура ТоварыНаСкладахКонтрольОстатков)», СтатусСообщения.ОченьВажное);

           КонецЕсли;

       //вернем обратно признак отказа от проведения документа
   ОтказПроведения = Отказ;
   ЗаголовокСообщения = Заголовок;

КонецПроцедуры // КонтрольОстатков()

   rintik

29 — 29.11.10 — 11:21

Танцы с бубном конечно, но может попробовать «Тестирование и исправление»?

   rintik

30 — 29.11.10 — 11:22

Конечно на копии сначала.

   andrejip

31 — 29.11.10 — 11:23

(26) дистрибов чего 1с ? Она лицензионная купленная на честно заработаные.

   andrejip

32 — 29.11.10 — 11:23

(29) не помогает.

   73

33 — 29.11.10 — 11:25

(31) имел ввиду дистрибутивов PostgreSQL

   rintik

34 — 29.11.10 — 11:26

Пользователь имеет полные права при проведении?

   rintik

35 — 29.11.10 — 11:26

Может RLS что то режет?

   Живой Ископаемый

36 — 29.11.10 — 11:29

2(28) это парнуха а не запрос… интересует именно запорос, который оттранслирован в (15)
который вот этот:
СтруктураШапкиДокумента, СтруктураПараметров, Заголовок, Отказ);
   ОбщийМодуль.ПроцедурыКонтроляОстатков.Модуль : 4599 : РезультатЗапроса = Запрос.Выполнить();’

интересует Запрос.Текст

   Живой Ископаемый

37 — 29.11.10 — 11:31

2(35) вообще-то предполагается что документы при проведении должны видеть все, и использовать для этого процедуры привелигерованного модуля… Но так или иначе — как мы можем об этом судить если он нам текст запроса не показывает, и есть ли в нем слово РАЗРЕШЕННЫЕ?

   andrejip

38 — 29.11.10 — 11:33

(37) ошибся.

   andrejip

39 — 29.11.10 — 11:34

Процедура ТоварыВРезервеНаСкладахКонтрольОстатков_Реализация(СтруктураШапкиДокумента, СтруктураПараметров, Заголовок, Отказ)

       ЕстьСоставНабора = (СтруктураПараметров.ИмяТабличнойЧасти = «Товары»);

   Если СтруктураПараметров.ИмяТабличнойЧасти = «ВозвратнаяТара» Тогда
       ЕстьХарактеристика  = Ложь;
       ЕстьСерия           = Ложь;
       ЕстьКачество        = Ложь;
   Иначе
       ЕстьХарактеристика  = Истина;
       ЕстьСерия           = СтруктураПараметров.ИспользоватьУказаниеСерийНоменклатурыПриРезервировании И СтруктураШапкиДокумента.ОбособленныйУчетТоваровПоЗаказамПокупателей;
       ЕстьКачество        = Истина;
   КонецЕсли;

       Если ЕстьСоставНабора Тогда

       ТекстЗапросаРеквизитыДокумента = »
           |    (ВЫБРАТЬ
           //Строки ТЧ Товары, в которых номенклатура — не комплект
           |            Док.Ссылка,
           |            Док.Номенклатура,
           |            Док.Склад,
           |            Док.СпособСписанияОстаткаТоваров,
           |            Док.ХарактеристикаНоменклатуры,
           |            Док.СерияНоменклатуры,
           |            Док.Коэффициент,
           |            Док.ЗаказПокупателя,
           |            Док.ЕдиницаИзмерения,
           |            Док.Количество
           |        ИЗ
           |            Документ.» + СтруктураПараметров.ИмяТаблицы + » КАК Док
           |        ГДЕ
           |            Док.Ссылка = &ДокументСсылка
           |            И НЕ Док.Номенклатура.Комплект
           |           И Док.СпособСписанияОстаткаТоваров = &ИзРезерва
           |        ОБЪЕДИНИТЬ ВСЕ
           |
           //Строки ТЧ Состав набора
           |        ВЫБРАТЬ
           |            Док.Ссылка,
           |            Док.Номенклатура,
           |            Док.Склад,
           |            Док.СпособСписанияОстаткаТоваров,
           |            Док.ХарактеристикаНоменклатуры,
           |            Док.СерияНоменклатуры,
           |            Док.Коэффициент,
           |            Док.ЗаказПокупателя,
           |            Док.ЕдиницаИзмерения,
           |            Док.Количество
           |        ИЗ
           |            (ВЫБРАТЬ
           |                ДокНаб.Ссылка,
           |                ДокНаб.Номенклатура,
           //Склад может быть указан в целом для набора в строке ТЧ Товары, или для каждого элемента набора в ТЧ СоставНабора
           |                ВЫБОР
           |                    КОГДА ДокНаб.Склад = &ПустойСклад ТОГДА ДокТов.Склад
           |                    ИНАЧЕ ДокНаб.Склад
           |                КОНЕЦ КАК Склад,
           //СпособСписанияОстатков может быть указан в целом для набора в строке ТЧ Товары, или для каждого элемента набора в ТЧ СоставНабора
           |                ВЫБОР
           |                    КОГДА ДокНаб.СпособСписанияОстаткаТоваров = &ПустойСпособСписания ТОГДА ДокТов.СпособСписанияОстаткаТоваров
           |                    ИНАЧЕ ДокНаб.СпособСписанияОстаткаТоваров
           |                КОНЕЦ КАК СпособСписанияОстаткаТоваров,
           |                ДокНаб.ХарактеристикаНоменклатуры,
           |                ДокНаб.СерияНоменклатуры,
           |                ДокНаб.ЕдиницаИзмерения.Коэффициент КАК Коэффициент,
           |                ДокТов.ЗаказПокупателя,
           |                ДокТов.ЕдиницаИзмерения,
           |                ДокНаб.Количество * ДокТов.Количество КАК Количество
           |            ИЗ
           |                Документ.» + СтруктураПараметров.ИмяДокумента + «.СоставНабора   КАК ДокНаб
           |                ЛЕВОЕ СОЕДИНЕНИЕ Документ.» + СтруктураПараметров.ИмяТаблицы + » КАК ДокТов
           |                    ПО ДокТов.КлючСтроки = ДокНаб.КлючСтроки
           |                     И ДокТов.Ссылка     = &ДокументСсылка
           |            ГДЕ
           |                ДокНаб.Ссылка = &ДокументСсылка
           |
           |            ) КАК Док
           |       ГДЕ Док.СпособСписанияОстаткаТоваров = &ИзРезерва
           |        ) КАК Док
           |»;

           Иначе
       ТекстЗапросаРеквизитыДокумента = »
           |    Документ.» + СтруктураПараметров.ИмяТаблицы + »
           |    КАК Док
           |»;
   КонецЕсли;

       // ПОЛУЧИМ УСЛОВИЯ ДЛЯ ВИРТУАЛЬНЫХ ТАБЛИЦ ОСТАТКОВ
   ПараметрыУсловий = Новый Структура(
           «ПолеСклад,ЕстьХарактеристика,ЕстьКачество,ЕстьСоставНабора,РеквизитДокументРезерва,ДопУсловияТабличнойЧасти»,
           «Склад»,
           ЕстьХарактеристика,
           ЕстьКачество,
           ЕстьСоставНабора,
           «ЗаказПокупателя»,
           » И Док.СпособСписанияОстаткаТоваров = &ИзРезерва И (НЕ Док.ЗаказПокупателя В (&МассивПустыхСсылок))»);

               ПараметрыУсловий.Вставить(«ИспользоватьХарактеристикиНоменклатуры», СтруктураПараметров.ИспользоватьХарактеристикиНоменклатуры);

       УсловияТаблицыОстатков = ПолучитьСтруктуруУсловийТаблицыОстатков(
           СтруктураПараметров.ИмяДокумента,
           СтруктураПараметров.ИмяТаблицы,
           Новый Структура(«Резерв»),
           ПараметрыУсловий);

               Запрос = Новый Запрос;

   // Установим параметры запроса
   Запрос.УстановитьПараметр(«ДокументСсылка»,        СтруктураШапкиДокумента.Ссылка);
   Запрос.УстановитьПараметр(«ИзРезерва»,             Перечисления.СпособыСписанияОстаткаТоваров.ИзРезерва);
   Запрос.УстановитьПараметр(«ПустойСпособСписания»,  Перечисления.СпособыСписанияОстаткаТоваров.ПустаяСсылка());
   Запрос.УстановитьПараметр(«ПустойСклад»,             Справочники.Склады.ПустаяСсылка());
   Запрос.УстановитьПараметр(«ПустаяХарактеристика»,  Справочники.ХарактеристикиНоменклатуры.ПустаяСсылка());
   Запрос.УстановитьПараметр(«ПустаяСерия»,             Справочники.СерииНоменклатуры.ПустаяСсылка());

   МассивПустыхСсылок = Новый Массив;
   МассивПустыхСсылок.Добавить(Неопределено);
   МассивПустыхСсылок.Добавить(Документы.ЗаказПокупателя.ПустаяСсылка());

       Запрос.УстановитьПараметр(«МассивПустыхСсылок», МассивПустыхСсылок);

   ТекстЗапроса = »
   |ВЫБРАТЬ // Запрос, контролирующий остатки на складах
   |    Док.Номенклатура                                        КАК Номенклатура,
   |    Док.Номенклатура.Представление                          КАК НоменклатураПредставление,
   |    Док.Номенклатура.ЕдиницаХраненияОстатков.Представление  КАК ЕдиницаХраненияОстатковПредставление,
   |   %ПОЛЕ_Док_Характеристика%                                КАК ХарактеристикаНоменклатуры,
   |    ПРЕДСТАВЛЕНИЕ(%ПОЛЕ_Док_Характеристика%)                КАК ХарактеристикаНоменклатурыПредставление,
   |   %ПОЛЕ_Док_Серия%                                        КАК СерияНоменклатуры,
   |    ПРЕДСТАВЛЕНИЕ(%ПОЛЕ_Док_Серия%)                        КАК СерияНоменклатурыПредставление,
   |    Док.ЗаказПокупателя                                    КАК ДокументРезерва,
   |   Док.Склад                                              КАК Склад,
   |   %ПОЛЕ_Док_Количество%                                    КАК ДокументКоличество,
   |    ЕСТЬNULL(МАКСИМУМ(Резервы.КоличествоОстаток), 0)        КАК РезервыКоличество
   |ИЗ
   |    «+ ТекстЗапросаРеквизитыДокумента + »
   |
   |ЛЕВОЕ СОЕДИНЕНИЕ
   |    РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(,» + УсловияТаблицыОстатков.Резерв + «) КАК Резервы
   |ПО
   |    Резервы.Склад = Док.Склад
   |    И Резервы.Номенклатура = Док.Номенклатура
   |    И Резервы.ДокументРезерва = Док.ЗаказПокупателя
   |   И Резервы.ХарактеристикаНоменклатуры = %СОЕДИНЕНИЕ_Характеристика_Остатки%
   |   И Резервы.СерияНоменклатуры = %СОЕДИНЕНИЕ_Серия_Остатки%
   |ГДЕ
   |    Не Док.Номенклатура.Комплект
   |    И Док.Ссылка  =  &ДокументСсылка
   |    И Док.СпособСписанияОстаткаТоваров = &ИзРезерва
   |    И (НЕ Док.ЗаказПокупателя В (&МассивПустыхСсылок))
   |СГРУППИРОВАТЬ ПО
   |
   |    Док.Номенклатура,
   |   %ПОЛЕ_Док_Характеристика%,
   |   %ПОЛЕ_Док_Серия%,
   |    Док.ЗаказПокупателя,
   |    Док.Склад
   |ИМЕЮЩИЕ ЕСТЬNULL(МАКСИМУМ(Резервы.КоличествоОстаток), 0) < %ПОЛЕ_Док_Количество%
   |ДЛЯ ИЗМЕНЕНИЯ РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки // Блокирующие чтение таблицы остатков регистра для разрешения коллизий многопользовательской работы
   |»;

       УчитыватьСерии = ложь;

       //По умолчанию отбор по пустой характеристике
   СОЕДИНЕНИЕ_Характеристика_Остатки = «ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)»;

       //По умолчанию отбор по пустой серии, т.к. для тары и договоров без ОУ резервы выполняются без серии
   СОЕДИНЕНИЕ_Серия_Остатки = «ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)»;

       Если СтруктураПараметров.ИмяТабличнойЧасти = «ВозвратнаяТара» Тогда
       //нет серии, характеристики, единицы измерения и коэффициента
       ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%ПОЛЕ_Док_Количество%»,»Сумма(Док.Количество)»);
       ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%ПОЛЕ_Док_Характеристика%»,»&ПустаяХарактеристика»);

   Иначе
       //есть характеристика, единица измерения и коэффициент.
       //Наличие серии зависит от того, ведется ли по договору обособленный учет.
       ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%ПОЛЕ_Док_Количество%»,»Сумма(ВЫРАЗИТЬ(Док.Количество * Док.Коэффициент / Док.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент КАК Число(15,3)))»);

               ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%ПОЛЕ_Док_Характеристика%»,»Док.ХарактеристикаНоменклатуры»);
       Если СтруктураПараметров.ИспользоватьХарактеристикиНоменклатуры Тогда
           СОЕДИНЕНИЕ_Характеристика_Остатки = «Док.ХарактеристикаНоменклатуры»;
       КонецЕсли;

       Если СтруктураПараметров.ИспользоватьУказаниеСерийНоменклатурыПриРезервировании Тогда
           //считаем что договор в заказах соответствует договору в шапке документа.
           Если СтруктураШапкиДокумента.ОбособленныйУчетТоваровПоЗаказамПокупателей Тогда
               УчитыватьСерии = истина;
               ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%ПОЛЕ_Док_Серия%»,»Док.СерияНоменклатуры»);
               Если СтруктураПараметров.ИспользоватьСерииНоменклатуры Тогда
                   СОЕДИНЕНИЕ_Серия_Остатки = «Док.СерияНоменклатуры»;
               КонецЕсли;
           КонецЕсли;
       КонецЕсли;
   КонецЕсли;
   Если не УчитыватьСерии Тогда
       ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%ПОЛЕ_Док_Серия%»,»&ПустаяСерия»);
   КонецЕсли;

       ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%СОЕДИНЕНИЕ_Характеристика_Остатки%», СОЕДИНЕНИЕ_Характеристика_Остатки);
   ТекстЗапроса = СтрЗаменить(ТекстЗапроса,»%СОЕДИНЕНИЕ_Серия_Остатки%», СОЕДИНЕНИЕ_Серия_Остатки);

   Если глЗначениеПеременной(«ИспользоватьБлокировкуДанных»)  Тогда
       Запрос.Текст =
           «ВЫБРАТЬ Склад, Номенклатура, ЗаказПокупателя» + ?(ЕстьХарактеристика, «, ХарактеристикаНоменклатуры», «») + »
           |ИЗ » + ТекстЗапросаРеквизитыДокумента + »
           |ГДЕ
           |    Не Док.Номенклатура.Комплект
           |    И Док.Ссылка  =  &ДокументСсылка
           |    И Док.СпособСписанияОстаткаТоваров = &ИзРезерва
           |    И (НЕ Док.ЗаказПокупателя В (&МассивПустыхСсылок))»;
       РезультатЗапросаДляБлокировки = Запрос.Выполнить();
       Если НЕ РезультатЗапросаДляБлокировки.Пустой() Тогда
           СтруктураПараметровБлокировки = Новый Структура(
               «ТипТаблицы,ИмяТаблицы,ИсточникДанных»
               ,»РегистрНакопления»
               ,»ТоварыВРезервеНаСкладах»
               ,РезультатЗапросаДляБлокировки);

                           СтруктураИсточникаДанных = Новый Структура(
               «Склад,Номенклатура,ДокументРезерва»
               ,»Склад»
               ,»Номенклатура»
               ,»ЗаказПокупателя»);
           Если ЕстьХарактеристика  И СтруктураПараметров.ИспользоватьХарактеристикиНоменклатуры Тогда
               СтруктураИсточникаДанных.Вставить(«ХарактеристикаНоменклатуры»,»ХарактеристикаНоменклатуры»);
           КонецЕсли;

                       ОбщегоНазначения.УстановитьУправляемуюБлокировку(СтруктураПараметровБлокировки,,СтруктураИсточникаДанных, Отказ, Заголовок);
       КонецЕсли;
   КонецЕсли;

       Запрос.Текст = ТекстЗапроса;
   РезультатЗапроса = Запрос.Выполнить();
   Если РезультатЗапроса.Пустой() Тогда
       Возврат;
   КонецЕсли;

       Выборка = РезультатЗапроса.Выбрать();
   Пока Выборка.Следующий() Цикл

       СтрокаСообщения = «Остатка резерва » +
       УправлениеЗапасами.ПредставлениеНоменклатуры(Выборка.НоменклатураПредставление,
                                 ?(СтруктураПараметров.ИмяТабличнойЧасти <> «ВозвратнаяТара», » «+Выборка.ХарактеристикаНоменклатурыПредставление, «»),
                                 ?(УчитыватьСерии, » «+Выборка.СерияНоменклатурыПредставление, «»)) +
       » на складе «»» + СокрЛП(Выборка.Склад) + «»» по документу «»» + СокрЛП(Выборка.ДокументРезерва) +
       «»» недостаточно.»;

       УправлениеЗапасами.ОшибкаНетОстатка(СтрокаСообщения, Выборка.РезервыКоличество, Выборка.ДокументКоличество,
       Выборка.ЕдиницаХраненияОстатковПредставление, Отказ, Заголовок);

   КонецЦикла;

КонецПроцедуры  //КонтрольОстатков_Реализация()

   andrejip

40 — 29.11.10 — 11:38

(34) полные.

   Живой Ископаемый

41 — 29.11.10 — 11:38

2(39) дядька… Ты можешь словить этот текст запроса отладчиком? Слови пожалуйста… Потому что то что ты будешь делать ближайшие пару часов — это видоизменять этот запрос и пытаться выполнять его в консоли запросов… До тех пор пока не сделайшь такой, при котором 1С не валится.. А уж потом ты попытаешься изменить код

   andrejip

42 — 29.11.10 — 11:41

2 (41) в том-то и дело (почему я бросил лог postgre),
у меня KUBUNTU стоит и wine при запуске отладчика падает. Сейчас версию postgre меняю на 8 4 1..

   andrejip

43 — 29.11.10 — 11:41

Кстати под windoй ошибка таже.

   andrejip

44 — 29.11.10 — 11:42

+(43) в смысле ошибка СУБД.

   andrejip

45 — 29.11.10 — 11:42

(41) сейчас виндовый комп найду и словлю отладчиком..

   Живой Ископаемый

46 — 29.11.10 — 11:43

ну короче, тут все ясно…

   andrejip

47 — 29.11.10 — 11:44

(46) что-то не так?

   Живой Ископаемый

48 — 29.11.10 — 11:51

думаю да.. Потому что либо вы не будете пользоваться резервированием в УПП… либо не будете пользоваться нынешним Постгресом в Линуксе..

   andrejip

49 — 29.11.10 — 11:52

(48) поясни пож.

   andrejip

50 — 29.11.10 — 11:54

(48) всё же есть надежда поправить к-либо запрос.

   Живой Ископаемый

51 — 29.11.10 — 11:54

2(49) что тут пояснять еще? у тебя запрос не выполняется, а ты даже не можешь отладчик запустить чтобы выцепить его текст. И как ты теперь собираешься в таких условиях работать?

   andrejip

52 — 29.11.10 — 11:56

(45)

   Живой Ископаемый

53 — 29.11.10 — 11:57

2(52) и что, каждый раз так будешь делать? отличный план

   andrejip

54 — 29.11.10 — 11:58

на след. неделе комп новый будет. там будет винд.

   Живой Ископаемый

55 — 29.11.10 — 12:00

Понятно.

   andrejip

56 — 30.11.10 — 14:15

ап.

   andrejip

57 — 30.11.10 — 14:15

ТекстЗапроса = »
   |ВЫБРАТЬ // Запрос, контролирующий остатки на складах
   |    Док.Номенклатура                                         КАК Номенклатура,
   |    Док.Номенклатура.Представление                           КАК НоменклатураПредставление,
   |    Док.Номенклатура.ЕдиницаХраненияОстатков.Представление  КАК ЕдиницаХраненияОстатковПредставление,
   |   %ПОЛЕ_Док_Характеристика%                                 КАК ХарактеристикаНоменклатуры,
   |    ПРЕДСТАВЛЕНИЕ(%ПОЛЕ_Док_Характеристика%)                 КАК ХарактеристикаНоменклатурыПредставление,
   |   %ПОЛЕ_Док_Серия%                                         КАК СерияНоменклатуры,
   |    ПРЕДСТАВЛЕНИЕ(%ПОЛЕ_Док_Серия%)                         КАК СерияНоменклатурыПредставление,
   |    Док.ЗаказПокупателя                                     КАК ДокументРезерва,
   |   Док.Склад                                               КАК Склад,
   |   %ПОЛЕ_Док_Количество%                                     КАК ДокументКоличество,
   |    ЕСТЬNULL(МАКСИМУМ(Резервы.КоличествоОстаток), 0)         КАК РезервыКоличество
   |ИЗ
   |    «+ ТекстЗапросаРеквизитыДокумента + »
   |
   |ЛЕВОЕ СОЕДИНЕНИЕ
   |    РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки(,» + УсловияТаблицыОстатков.Резерв + «) КАК Резервы
   |ПО
   |    Резервы.Склад = Док.Склад
   |    И Резервы.Номенклатура = Док.Номенклатура
   |    И Резервы.ДокументРезерва = Док.ЗаказПокупателя
   |   И Резервы.ХарактеристикаНоменклатуры = %СОЕДИНЕНИЕ_Характеристика_Остатки%
   |   И Резервы.СерияНоменклатуры = %СОЕДИНЕНИЕ_Серия_Остатки%
   |ГДЕ
   |    Не Док.Номенклатура.Комплект
   |    И Док.Ссылка  =  &ДокументСсылка
   |     И Док.СпособСписанияОстаткаТоваров = &ИзРезерва
   |    И (НЕ Док.ЗаказПокупателя В (&МассивПустыхСсылок))
   |СГРУППИРОВАТЬ ПО
   |
   |    Док.Номенклатура,
   |   %ПОЛЕ_Док_Характеристика%,
   |   %ПОЛЕ_Док_Серия%,
   |    Док.ЗаказПокупателя,
   |    Док.Склад
   |ИМЕЮЩИЕ ЕСТЬNULL(МАКСИМУМ(Резервы.КоличествоОстаток), 0) < %ПОЛЕ_Док_Количество%
   |ДЛЯ ИЗМЕНЕНИЯ РегистрНакопления.ТоварыВРезервеНаСкладах.Остатки // Блокирующие чтение таблицы остатков регистра для разрешения коллизий многопользовательской работы
   |»;

   andrejip

58 — 30.11.10 — 14:16

на нем вылетает ошибка. (0)(1)

   andrejip

59 — 30.11.10 — 14:18

аp

   Живой Ископаемый

60 — 30.11.10 — 14:24

э… Док.ЗаказПокупателя , Док.Склад — какого типа?
и опять же — а это что за лажа: «|    «+ ТекстЗапросаРеквизитыДокумента + «»?
Выполни этот запрос в консоли.

  

   andrejip

61 — 30.11.10 — 14:26

ап-=

  

andrejip

62 — 13.12.10 — 09:38

21 января, 2019 12:06 пп
24 753 views
| Комментариев нет

Ubuntu

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

В системах управления реляционными базами данных запрос – это любая команда, используемая для извлечения данных из таблицы. В языке структурированных запросов (SQL) запросы почти всегда выполняются с помощью оператора SELECT.

В этом мануале мы обсудим основной синтаксис SQL-запросов, а также некоторые из наиболее часто используемых функций и операторов. Мы также попрактикуемся в создании запросов SQL на тестовых данных в БД PostgreSQL.

PostgreSQL (часто просто «Postgres») – это систему управления реляционными базами данных с объектно-ориентированным подходом (это означает, что в схемах PostgreSQL информация может быть представлена в виде объектов или классов). PostgreSQL тесно связан со стандартным SQL, хотя он также включает некоторые функции, которых нет в других реляционных СУБД.

Требования

В общем, команды и понятия, представленные в этом мануале, могут использоваться в любой операционной системе на базе Linux и в любом программном обеспечении SQL. Однако мануал был написан специально для сервера Ubuntu 18.04 и PostgreSQL. Для работы вам понадобится:

  • Сервер Ubuntu 18.04 с пользователем sudo. Начальная настройка сервера описана здесь.
  • Предварительно установленная система PostgreSQL. Инструкции по установке можно найти в мануале Установка и использование PostgreSQL в Ubuntu 18.04.

Создание тестовой базы данных

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

В качестве БД, которую мы будем использовать в этом руководстве, мы предлагаем следующий сценарий.

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

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

Для начала откройте командную строку PostgreSQL:

sudo -u postgres psql

Примечание: Если вы полностью выполнили мануал по установке PostgreSQL в Ubuntu 18.04, вероятно, вы настроили новую роль. В этом случае вы можете подключиться к командной строке Postgres с помощью следующей команды, заменив 8host своим именем пользователя:

sudo -u 8host psql

Создайте БД:

CREATE DATABASE birthdays;

Выберите эту БД:

c birthdays

Затем создайте в этой базе данных две таблицы. Первую таблицу можно использовать, чтобы отслеживать результаты в боулинге. Следующая команда создаст таблицу под названием tourneys. В ней будут столбцы с именами подруг (name), количество выигранных ими турниров (wins), их лучшие результаты за все время (best) и размер ботинок для боулинга, которые они носят (size):

CREATE TABLE tourneys (
name varchar(30),
wins real,
best real,
size real
);

Запустив эту команду и заполнив ее заголовками столбцов, вы увидите такой вывод:

CREATE TABLE

Теперь добавьте в таблицу какие-нибудь данные:

INSERT INTO tourneys (name, wins, best, size)
VALUES ('Dolly', '7', '245', '8.5'),
('Etta', '4', '283', '9'),
('Irma', '9', '266', '7'),
('Barbara', '2', '197', '7.5'),
('Gladys', '13', '273', '8');

Команда вернет:

INSERT 0 5

После этого создайте еще одну таблицу в той же базе данных. Ее можно использовать для хранения информации о любимых блюдах подруг на день рождения. Следующая команда создает таблицу dinners, где будут столбцы с именами подруг, их датой рождения (birthdate), их любимым блюдом (entree), гарниром (side) и десертом (dessert):

CREATE TABLE dinners (
name varchar(30),
birthdate date,
entree varchar(30),
side varchar(30),
dessert varchar(30)
);

После запуска команда выведет:

CREATE TABLE

Теперь заполните таблицу данными:

VALUES ('Dolly', '1946-01-19', 'steak', 'salad', 'cake'),
('Etta', '1938-01-25', 'chicken', 'fries', 'ice cream'),
('Irma', '1941-02-18', 'tofu', 'fries', 'cake'),
('Barbara', '1948-12-25', 'tofu', 'salad', 'ice cream'),
('Gladys', '1944-05-28', 'steak', 'fries', 'ice cream');
INSERT 0 5

Теперь у вас есть данные, на которых можно потренироваться.

Оператор SELECT

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

В общем SQL-запросы следуют такому синтаксису:

SELECT column_to_select FROM table_to_select WHERE certain_conditions_apply;

Например, чтобы извлечь столбец name из таблицы dinners, нужен такой запрос:

SELECT name FROM dinners;
name
---------
Dolly
Etta
Irma
Barbara
Gladys
(5 rows)

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

SELECT name, birthdate FROM dinners;
name    | birthdate
--------+------------
Dolly   | 1946-01-19
Etta    | 1938-01-25
Irma    | 1941-02-18
Barbara | 1948-12-25
Gladys  | 1944-05-28
(5 rows)

Вместо того чтобы называть конкретный столбец или набор столбцов, вы можете использовать оператор SELECT со звездочкой (*) – она служит заполнителем, представляющим все столбцы в таблице. Следующая команда отобразит все столбцы таблицы tourneys:

SELECT * FROM tourneys;
name    | wins | best | size
--------+------+------+------
Dolly   |    7 |  245 |  8.5
Etta    |    4 |  283 |    9
Irma    |    9 |  266 |    7
Barbara |    2 |  197 |  7.5
Gladys  |   13 |  273 |    8
(5 rows)

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

. . . WHERE column_name comparison_operator value

Оператор сравнения в выражении WHERE определяет способ сравнения указанного столбца со значением. Вот некоторые распространенные операторы сравнения SQL:

Оператор Действие
= Равно
!= Не равно
< Меньше, чем
> Больше, чем
<= Меньше или равно
>= Больше или равно
BETWEEN проверяет, находится ли значение в заданном диапазоне
IN проверяет, содержится ли значение строки в наборе указанных значений
EXISTS проверяет, существуют ли строки при заданных условиях
LIKE проверяет, соответствует ли значение указанной строке
IS NULL Проверяет значения NULL
IS NOT NULL Проверяет все значения, кроме NULL

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

SELECT size FROM tourneys WHERE name = 'Irma';
size
------
7
(1 row)

SQL позволяет использовать подстановочных знаков, и это особенно удобно при работе с выражениями WHERE. Знак процента (%) представляют ноль или более неизвестных символов, а подчеркивания (_) представляют один неизвестный символ. Они полезны, если вы пытаетесь найти конкретную запись в таблице, но не знаете точно, что это за запись. Чтобы проиллюстрировать это, предположим, что вы забыли любимое блюдо нескольких своих подруг, но вы уверены, что это блюдо начинается на t. Вы можете найти его название с помощью запроса:

SELECT entree FROM dinners WHERE entree LIKE 't%';
entree
-------
tofu
tofu
(2 rows)

Исходя из вышеприведенного вывода, это tofu.

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

SELECT name AS n, birthdate AS b, dessert AS d FROM dinners;
n       |     b      |     d
--------+------------+-----------
Dolly   | 1946-01-19 | cake
Etta    | 1938-01-25 | ice cream
Irma    | 1941-02-18 | cake
Barbara | 1948-12-25 | ice cream
Gladys  | 1944-05-28 | ice cream
(5 rows)

Как видите, теперь SQL отображает столбец name как n, столбец birthdate как b и dessert как d.

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

Агрегатные функции

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

Функция COUNT считает и возвращает количество строк, соответствующих определенным критериям. Например, если вы хотите узнать, сколько ваших друзей предпочитают тофу, вы можете выполнить этот запрос:

SELECT COUNT(entree) FROM dinners WHERE entree = 'tofu';
count
-------
2
(1 row)

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

SELECT AVG(best) FROM tourneys;
avg
-------
252.8
(1 row)

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

SELECT SUM(wins) FROM tourneys;
sum
-----
35
(1 row)

Обратите внимание, функции AVG и SUM работают правильно только с числовыми данными. Если вы попытаетесь использовать их для нечисловых данных, это приведет к ошибке или к 0, в зависимости от того, какую СУБД вы используете.

SELECT SUM(entree) FROM dinners;
ERROR:  function sum(character varying) does not exist
LINE 1: select sum(entree) from dinners;
^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

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

SELECT MIN(wins) FROM tourneys;
min
-----
2
(1 row)

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

SELECT MAX(wins) FROM tourneys;
max
-----
13
(1 row)

В отличие от SUM и AVG, функции MIN и MAX могут использоваться как для числовых, так и для буквенных типов данных. При запуске в столбце со строковыми значениями функция MIN отображает первое значение в алфавитном порядке:

SELECT MIN(name) FROM dinners;
min
---------
Barbara
(1 row)

Аналогично MAX покажет последнее значение в алфавитном порядке:

SELECT MAX(name) FROM dinners;
max
------
Irma
(1 row)

Агрегатные функции широко применяются в СУБД. Они особенно полезны в выражениях GROUP BY, которые мы рассмотрим в следующем разделе вместе с несколькими другими операторами сортировки наборов результатов.

Управление выводом запроса

В дополнение к FROM и WHERE есть несколько других операторов, которые используются для управления результатами запроса SELECT. В этом разделе мы объясним некоторые из наиболее часто используемых операторов и рассмотрим их на примерах.

Одним из наиболее часто используемых операторов, кроме FROM и WHERE, является GROUP BY. Обычно он используется, когда вы выполняете агрегатную функцию для одного столбца, но в отношении сопоставления значений в другом.

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

SELECT COUNT(name), entree FROM dinners GROUP BY entree;
count | entree
------+---------
1     | chicken
2     | steak
2     | tofu
(3 rows)

Оператор ORDER BY используется для сортировки результатов запроса. По умолчанию числовые значения сортируются в порядке возрастания, а текстовые значения сортируются в алфавитном порядке. Для примера в следующем запросе перечислены имена и даты рождения, результаты отсортированы по дате рождения:

SELECT name, birthdate FROM dinners ORDER BY birthdate;
name    | birthdate
--------+------------
Etta    | 1938-01-25
Irma    | 1941-02-18
Gladys  | 1944-05-28
Dolly   | 1946-01-19
Barbara | 1948-12-25
(5 rows)

По умолчанию ORDER BY сортирует результаты в порядке возрастания. Чтобы отсортировать их в обратном порядке, добавьте DESC:

SELECT name, birthdate FROM dinners ORDER BY birthdate DESC;
name    | birthdate
--------+------------
Barbara | 1948-12-25
Dolly   | 1946-01-19
Gladys  | 1944-05-28
Irma    | 1941-02-18
Etta    | 1938-01-25
(5 rows)

Как упоминалось ранее, WHERE используется для фильтрации результатов на основе определенных условий. Однако если вы используете WHERE с агрегатной функцией, он вернет ошибку. Для примера попробуем выяснить, какой гарнир нравится как минимум трем подругам:

SELECT COUNT(name), side FROM dinners WHERE COUNT(name) >= 3;
ERROR:  aggregate functions are not allowed in WHERE
LINE 1: SELECT COUNT(name), side FROM dinners WHERE COUNT(name) >= 3...

Оператор HAVING добавлен в SQL для выполнения функций, аналогичных WHERE, но совместимых с агрегатными функциями. Разница между этими двумя операторами в том, что WHERE применяется к отдельным записям, а HAVING – к групповым. Для этого при каждом выполнении HAVING также должен присутствовать оператор GROUP BY.

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

SELECT COUNT(name), side FROM dinners GROUP BY side HAVING COUNT(name) >= 3;
count | side
------+-------
3     | fries
(1 row)

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

Запрос данных из нескольких таблиц

Чаще всего база данных содержит несколько таблиц, каждая из которых содержит разные наборы данных. SQL предоставляет несколько способов выполнения одного запроса для нескольких таблиц.

Оператор JOIN можно использовать для объединения строк из двух или более таблиц в результате запроса. Это достигается путем нахождения одинакового столбца между таблицами и соответствующей сортировки результатов в выходных данных.

Выражение SELECT с оператором JOIN, как правило, работает по такому синтаксису:

SELECT table1.column1, table2.column2
FROM table1
JOIN table2 ON table1.related_column=table2.related_column;

Обратите внимание, поскольку оператор JOIN сравнивает содержимое нескольких таблиц, в предыдущем выражении указывается, из какой таблицы нужно выбрать каждый столбец: сначала указывается название таблицы, а через точку – название столбца. Вы можете указать, из какой таблицы должен быть выбран столбец, хотя это не обязательно при выборе из одной таблицы. Давайте рассмотрим пример.

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

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
JOIN dinners ON tourneys.name=dinners.name;
name    | size | birthdate
--------+------+------------
Dolly   |  8.5 | 1946-01-19
Etta    |    9 | 1938-01-25
Irma    |    7 | 1941-02-18
Barbara |  7.5 | 1948-12-25
Gladys  |    8 | 1944-05-28
(5 rows)

Оператор JOIN, используемый в этом примере без каких-либо других аргументов, является внутренним JOIN. Это означает, что он выбирает в обеих таблицах все записи, у которых есть общее значение (в данном случае – имя), и выводит их в наборе результатов, в то время как все остальные записи исключаются. Чтобы проиллюстрировать эту функцию, давайте добавим в каждую таблицу новые строки, у которых не будет общего значения:

INSERT INTO tourneys (name, wins, best, size)
VALUES ('Bettye', '0', '193', '9');
INSERT INTO dinners (name, birthdate, entree, side, dessert)
VALUES ('Lesley', '1946-05-02', 'steak', 'salad', 'ice cream');

А теперь повторите запрос:

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
JOIN dinners ON tourneys.name=dinners.name;
name    | size | birthdate
--------+------+------------
Dolly   |  8.5 | 1946-01-19
Etta    |    9 | 1938-01-25
Irma    |    7 | 1941-02-18
Barbara |  7.5 | 1948-12-25
Gladys  |    8 | 1944-05-28
(5 rows)

Обратите внимание, что, поскольку в таблице tourneys нет записи для Lesley, а в таблице dinners нет записи для Bettye, эти записи отсутствуют в выходных данных.

Однако возможно вернуть все записи из одной из таблиц, используя внешнее соединение JOIN. Внешние JOIN записываются как LEFT JOIN, RIGHT JOIN или FULL JOIN.

Предложение LEFT JOIN возвращает все записи из левой таблицы и только совпадающие записи из правой таблицы. В контексте внешнего соединения левая таблица – это таблица, на которую ссылается FROM, а правая – любая другая таблица, на которую есть ссылка после оператора JOIN.

Выполните предыдущий запрос еще раз, но на этот раз используйте LEFT JOIN:

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
LEFT JOIN dinners ON tourneys.name=dinners.name;

Эта команда выведет каждую запись из левой таблицы (в данном случае tourneys), даже если в правой таблице нет совпадающей записи. Каждый раз, когда в правой таблице нет подходящей записи, она возвращается как пустое значение или NULL, в зависимости от СУБД.

name   | size | birthdate
---------+------+------------
Dolly   |  8.5 | 1946-01-19
Etta    |    9 | 1938-01-25
Irma    |    7 | 1941-02-18
Barbara |  7.5 | 1948-12-25
Gladys  |    8 | 1944-05-28
Bettye  |    9 |
(6 rows)

Повторите запрос с оператором RIGHT JOIN:

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
RIGHT JOIN dinners ON tourneys.name=dinners.name;

Это вернет все записи из правой таблицы (dinners). Поскольку дата рождения Лесли записана в правой таблице, но для нее нет соответствующей строки в левой таблице, в столбцах name и size в этой строке будут пустые значения:

name   | size | birthdate
--------+------+------------
Dolly   |  8.5 | 1946-01-19
Etta    |    9 | 1938-01-25
Irma    |    7 | 1941-02-18
Barbara |  7.5 | 1948-12-25
Gladys  |    8 | 1944-05-28
.       |      | 1946-05-02
(6 rows)

Обратите внимание, что левые и правые соединения могут быть записаны как LEFT OUTER JOIN или RIGHT OUTER JOIN, хотя OUTER и так подразумевается. Аналогично, INNER JOIN дает тот же результат, что и простой JOIN.

Для некоторых дистрибутивов СУБД, включая PostgreSQL, существует четвертое условие соединения, называемое FULL JOIN. FULL JOIN вернет все записи из каждой таблицы, включая все нулевые значения:

SELECT tourneys.name, tourneys.size, dinners.birthdate
FROM tourneys
FULL JOIN dinners ON tourneys.name=dinners.name;
name    | size | birthdate
--------+------+------------
Dolly   |  8.5 | 1946-01-19
Etta    |    9 | 1938-01-25
Irma    |    7 | 1941-02-18
Barbara |  7.5 | 1948-12-25
Gladys  |    8 | 1944-05-28
Bettye  |    9 |
.       |      | 1946-05-02
(7 rows)

Примечание: На момент написания MySQL и MariaDB не поддерживают FULL JOIN.

В качестве альтернативы FULL JOIN для запроса всех записей из нескольких таблиц, вы можете использовать оператор UNION.

Оператор UNION работает немного иначе, чем JOIN: вместо вывода результатов из нескольких таблиц в виде уникальных столбцов с помощью одного оператора SELECT он объединяет результаты двух операторов SELECT в один столбец.

Рассмотрим такой запрос:

SELECT name FROM tourneys UNION SELECT name FROM dinners;

Он удалит все дублируемые записи, так как это поведение UNION по умолчанию.

name
---------
Irma
Etta
Bettye
Gladys
Barbara
Lesley
Dolly
(7 rows)

Чтобы вывести все записи, включая повторы, используйте UNION ALL.

SELECT name FROM tourneys UNION ALL SELECT name FROM dinners;
name
---------
Dolly
Etta
Irma
Barbara
Gladys
Bettye
Dolly
Etta
Irma
Barbara
Gladys
Lesley
(12 rows)

Значения и количество столбцов в результате отражают имя и количество столбцов, запрошенных первым оператором SELECT. Обратите внимание, что при использовании UNION для запроса нескольких столбцов из более, чем одной таблицы каждый оператор SELECT должен запрашивать одинаковое количество столбцов, соответствующие столбцы должны иметь одинаковые типы данных, а также идти в одном порядке в каждом операторе SELECT. В следующем примере показано, что может произойти, если вы используете предложение UNION для двух операторов SELECT, которые запрашивают разное количество столбцов:

SELECT name FROM dinners UNION SELECT name, wins FROM tourneys;
ERROR:  each UNION query must have the same number of columns
LINE 1: SELECT name FROM dinners UNION SELECT name, wins FROM tourne...

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

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

SELECT name, wins FROM tourneys
WHERE wins > (
SELECT wins FROM tourneys WHERE name = 'Barbara'
);
name   | wins
-------+------
Dolly  |    7
Etta   |    4
Irma   |    9
Gladys |   13
(4 rows)

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

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

SELECT name, size FROM tourneys AS t
WHERE wins > (
SELECT AVG(wins) FROM tourneys WHERE size = t.size
);

Чтобы обработать запрос, СУБД должна сначала собрать столбцы name и size из внешнего запроса. Затем она сравнивает каждую строку из этого набора результатов с результатами внутреннего запроса, который определяет среднее количество побед для людей с одинаковым размером обуви. Поскольку у вас есть только две подруги с одинаковым размером обуви, в наборе результатов получится только одна строка:

name | size
-----+------
Etta |    9
(1 row)

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

SELECT name, entree, side, dessert
FROM dinners
WHERE name = (SELECT name FROM tourneys
WHERE wins = (SELECT MAX(wins) FROM tourneys));
name   | entree | side  |  dessert
-------+--------+-------+-----------
Gladys | steak  | fries | ice cream
(1 row)

Обратите внимание: этот запрос не только содержит подзапрос, но также еще один подзапрос внутри него.

Заключение

Запросы являются одной из наиболее часто выполняемых задач в области управления базами данных. Существует ряд инструментов администрирования баз данных (таких как phpMyAdmin и pgAdmin), которые позволяют выполнять запросы и визуализировать результаты, но выдача операторов SELECT из командной строки по-прежнему является широко распространенным рабочим процессом, который также может предоставить вам больший контроль над своими данными.

Если вы новичок в SQL, мы рекомендуем вам ознакомиться с нашим мануалом Краткий справочник по управлению базой данных SQL и с официальной документацией PostgreSQL. Кроме того, если вы хотите больше узнать о SQL и реляционных базах данных, вам могут быть интересны следующие мануалы:

  • SQL, NoSQL и другие модели баз данных
  • Логическая репликация PostgreSQL 10 в Ubuntu 18.04
  • Защита PostgreSQL от автоматизированных хакерских атак

Tags: PostgreSQL, SQL, Ubuntu 18.04

Понравилась статья? Поделить с друзьями:
  • Error during initialization no iwd files found in main call of duty
  • Error during initialization missing config file default cfg during initialization
  • Error during initialization miles sound system как решить
  • Error during initialization exe err not found configure mp csv
  • Error during initialization exe err mss init failed mp call of duty 2