Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Main_Table PK User_Constraints 22 страница

Main_Table PK User_Constraints 11 страница | Main_Table PK User_Constraints 12 страница | Main_Table PK User_Constraints 13 страница | Main_Table PK User_Constraints 14 страница | Main_Table PK User_Constraints 15 страница | Main_Table PK User_Constraints 16 страница | Main_Table PK User_Constraints 17 страница | Main_Table PK User_Constraints 18 страница | Main_Table PK User_Constraints 19 страница | Main_Table PK User_Constraints 20 страница |


Читайте также:
  1. 1 страница
  2. 1 страница
  3. 1 страница
  4. 1 страница
  5. 1 страница
  6. 1 страница
  7. 1 страница

4. Процент от всех сделок, в которых принимали участие торговые агенты.

 

With T as (Select Cust_First_Name, Cust_Last_Name, Sum(Unit_Price) as sums

From Customers Join Orders Using(Customer_Id)

Join Order_Items Using(Order_Id)

Group By Cust_First_Name, Cust_Last_Name)

 

Select Cust_First_Name, Cust_Last_Name, Round(Sums/(Select Sum(Sums) From T),5) *100 As "%"

From T;

Результат:

 

CUST_FIRST_NAME CUST_LAST_NAME %

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

Maurice Hasan 1,007

Divine Aykroyd 0,391

Dheeraj Alexander 0,097

Manisha Taylor 1,043

Gustav Steenburgen 4,395

Markus Rampling 7,094

Sachin Spielberg 1,608

Matthias Hannah 1,833

Maurice Mahoney 3,633

Maximilian Henner 0,313

Dieter Matthau 0,501

Divine Sheen 3,229

Frederico Romero 2,731

Eddie Boyer 3,982

Charlotte Kazan 0,138

Christian Cage 2,211

Sidney Capshaw 0,689

Matthias MacGraw 3,41

Meenakshi Mason 4,083

Ishwarya Roberts 6,27

Geraldine Martin 2,133

Frederic Grodin 0,406

Ernest Weaver 0,075

Guillaume Edwards 3,817

Diane Higgins 0,073

Dianne Sen 0,387

Elizabeth Brown 0,751

Goldie Montand 2,159

Eddie Stern 0,311

Ernest George 0,044

Ernest Chandar 0,085

Charlotte Fonda 0,198

Gerard Hershey 0,006

Dheeraj Davis 1,196

Sivaji Landis 5,501

Sachin Neeson 0,991

Frederico Lyon 0,861

Hema Voight 3,168

Harrison Sutherland 3,414

Matthias Cruise 5,464

Mammutti Pacino 2,996

Elia Fawcett 3,17

Maurice Daltrey 1,102

Goldie Slater 2,548

Harrison Pacino 5,181

Harry Dean Fonda 0,85

Constantin Welles 4,458

 

47 rows selected

 

Комментарий:

Подзапрос Т возвращает Сумму выручки сделок, которые сопровождал торговый агент

Для этого связываем таблицы Customers, Orders, Order_Items

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

 


11. Вывести календарь на текущий месяц (2 цифры месяца месяц (по английски большими буквами) год (четыре цифры) день недели (по-английски маленькими буквами)) все через один пробел. Хвостовых и лидирующих пробелов быть не должно

 

With X As (Select Trunc(Sysdate,'mm')+Level-1 D

From Dual Connect By Level <= To_Char(Last_Day(Sysdate),'dd'))

Select To_Char(D,'dd fmMONTH yyyy day','NLS_DATE_LANGUAGE=AMERICAN') Calendar

From X Order By 1;

 

CALENDAR

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

01 MAY 2012 tuesday

02 MAY 2012 wednesday

03 MAY 2012 thursday

04 MAY 2012 friday

05 MAY 2012 saturday

06 MAY 2012 sunday

07 MAY 2012 monday

08 MAY 2012 tuesday

09 MAY 2012 wednesday

10 MAY 2012 thursday

11 MAY 2012 friday

12 MAY 2012 saturday

13 MAY 2012 sunday

14 MAY 2012 monday

15 MAY 2012 tuesday

16 MAY 2012 wednesday

17 MAY 2012 thursday

18 MAY 2012 friday

19 MAY 2012 saturday

20 MAY 2012 sunday

21 MAY 2012 monday

22 MAY 2012 tuesday

23 MAY 2012 wednesday

24 MAY 2012 thursday

25 MAY 2012 friday

26 MAY 2012 saturday

27 MAY 2012 sunday

28 MAY 2012 monday

29 MAY 2012 tuesday

30 MAY 2012 wednesday

31 MAY 2012 thursday

 

31 rows selected

 

Комментарий:

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

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

 


 

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

 

Пример вывода:

LAST_NAME NUM_S NUM_DEP
King    
Kochhar    
De Haan    
Hunold    
Greenberg    
Raphaely    
Weiss    
………………    

 

Select Last_Name,

(Select Count(*)

From Employees T2

Start With T2.Manager_Id=T1.Employee_Id

Connect By Prior Employee_Id = Manager_Id) NUM_S,

(Select Count(*)

From Employees T2

Where T1.Department_Id=T2.Department_Id

Start With T2.Manager_Id=T1.Employee_Id

Connect By Prior Employee_Id = Manager_Id) NUM_Dept

From Employees T1

 

LAST_NAME NUM_S NUM_DEPT

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

King 106 2

Kochhar 11 0

De Haan 5 0

Hunold 4 4

Ernst 0 0

Weiss 8 8

Fripp 8 8

Kaufling 8 8

Mikkilineni 0 0

Landry 0 0

Rogers 0 0

Patel 0 0

Rajs 0 0

Russell 6 6

Partners 6 6

Errazuriz 6 6

Cambrault 6 6

Zlotkey 6 5

Bell 0 0

Everett 0 0

McCain 0 0

Jones 0 0

Walsh 0 0

Feeney 0 0

OConnell 0 0

 

107 rows selected

Комментарий:

NUM_S, --количество подчиненных всех уровней. Перебирая всех сотрудников у которых Manager_Id равен текущему Employee_Id(меняется при изменении фамилии)

NUM_Dept --количество подчиненных всех уровней, работающих в тех же отделах. Так же как в NUM_S только добавлено условие одинакового отдела

 

13. Вычислить число Пи с точностью 40 знаков после запятой.

Для расчета использовать быстро сходящуюся последовательность

Select B||A "Число пи с точ. до 40 знака"

From (

Select Substr((Sum(Substr(Pi, 4, 100))*10),2) A, Substr(Sum(Pi),1,4) B

From (

Select Pi

From Dual

Model

Return All Rows

Dimension By (0 D)

Measures (0 Pi)

Rules Iterate (100)

(Pi[iteration_number] = 1 /

Power(16, (iteration_number)) *

(

4 / (8 * (iteration_number) + 1) -

2 / (8 * (iteration_number) + 4) -

1 / (8 * (iteration_number) + 5) -

1 / (8 * (Iteration_Number) + 6)

)

)));

Результат:

Число пи с точ. до 40 знака

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

3,1415873903473333870692083336288769175294


Комментарий:

Из этих слагаемых(полученных через model) будет складываться наше число пи

Для каждого к:

 

Substr((Sum(Substr(Pi, 4, 100))*10),2) A, Substr(Sum(Pi),1,4) B

A – считаем сумму слагаемых начиная с третьего знака после запятой.

B – считаем сумму слагаемых начиная с первого знака до второго после запятой

Соединим полученные суммы и получим результат с точностью 40 знаков после запятой

 

14. Определить ближайший к заданной дате год, когда 31 декабря придется на субботу.

 

Select To_Char(Datex, 'YYYY') As Year

From (Select To_Date('&date', 'DD-MM-YYYY') As Datex From Dual)

Model

Dimension By (0 Dim)

Measures(Datex)

Rules Iterate (100500) Until (To_Char(Datex[0]) Like '31.12%' And To_Char(Datex[0], 'D') = '6')

(DateX[0] =

Case

When To_Char(Datex[0], 'MM') = '12' Then

Case

When To_Char(Datex[0], 'DD') = '31' Then

Case

When To_Char(Datex[0], 'D') = '6' Then Datex[0]

Else Datex[0] + 1

End

Else Datex[0] + 1 End

Else Datex[0] + To_Yminterval('00-01') End);

 

Комментарий:

Из таблицы dual выбираем значение даты, когда 31 декабря придется на субботу.

Для Этого С Помощью Model Изменяем Введенную Дату Пока Она Не Станет Искомой

-Если Месяц Не Декабрь, Прибавляем К Дате Месяц

-Если Месяц Декабрь, Но Не 31 Или Же 31, Но Не 6 День Недели (Суббота), То Добавляем День

-Если все условия соблюдены, дата не изменяется, происходит выход из цикла по условию

To_Char(Date_Sun[0]) Like '31.12%' And To_Char(Date_Sun[0], 'D') = '6'

Из полученной даты извлекаем год и выводим его на экран.

 

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

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

В результат вывести:

1.Идентификатор подразделения компании, к которому приписан сотрудник.

2. Фамилию сотрудника.

3.Оклад, установленный сотруднику.

В команде SELECT запрещается использовать:

· Фразы WITH, GROUP BY,HAVING, ORDER BY, CONNECT BY, START WITH,

· Условия IN, =ANY, =SOME, NOT IN, <> ALL, EXISTS, NOT EXISTS,

· Подзапросы (subqueries), в том числе подзапросы во фразе FROM,

· Иерархические запросы (hierarchical queries),

· Скалярное выражение подзапроса (scalar subquery expression),

· Агрегатные функции – MIN,MAX, SUM,COUNT, AVG и др.

· Аналитические функции (analytic functions)

 

Select E2.Department_Id, E2.Last_Name, E2.Salary

From Employees E0 Join Employees E1 On (E0.Department_Id=E1.Department_Id And E0.Salary>E1.Salary) ----отсекаем минимальные зарплаты

---связываем каждого с каждым с разными зарплатами

Right Outer Join Employees E2 On (E0.Employee_Id=E2.Employee_Id) -- свяжем соед.ROJ с полноценной таблицей

Where E0.Salary Is Null

----и у тех у кого E0 заполнится Nullми (т.е. у тех у кого минимальные зарплаты) выведем

Order By E2.Department_Id;

 

Комментарий:

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

Потом свяжем соединением Right Outer Join с полноценной таблицей

И у тех у кого E0 заполнится Nullми (т.е. у тех у кого минимальные зарплаты) выведем (поставив условие Where E0.Salary Is Null)

 

16. Создать запрос для определения произведения всех чисел в столбце Department_Id таблицы Departments.

 

Select Exp(Sum(Ln(Department_Id))) as "Произведение номеров отделов"

From Departments;

 

Произведение номеров отделов

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

 

Комментарий:

Распишем нашу формулу:

Произведение номеров отделов=x

x = (Id1 * id2 *id3*….)

ln(x) = ln(Id1 * id2 *id3*….)

ln(x) = ln(Id1) + ln(id2) + ln(id3)+… => SUM(LN(Department_id))

x = e (ln(x)) => EXP(SUM(LN(Department_id)))

x = 10888869450418352160768000000000000002060000000000000000

 

17. В произвольной строке, состоящей из символьных элементов, разделенных запятыми, отсортировать элементы по алфавиту. Например, символьную строку

abc,cde,ef,gh,mn,test,ss, df,fw,ewe,wwe

преобразовать к виду:

abc,cde,df,ef,ewe, fw,gh,mn,ss,test,wwe.

 

With T As

(Select Regexp_Substr('abc,cde,ef,gh,mn,test,ss,df,fw,ewe,wwe', '[^,]+', 1, Level) Str

From Dual

Connect By Instr('abc,cde,ef,gh,mn,test,ss,df,fw,ewe,wwe', ',', 1, Level - 1) > 0

Order By 1)

 

Select 'abc,cde,ef,gh,mn,test,ss, df,fw,ewe,wwe' Исходник, Max(Ltrim(Sys_Connect_By_Path(Str, ', '), ', ')) Результат

From (Select T.Str,Rownum Rn

From T)

Start With Rn=1

Connect By Prior Rn+1=Rn;

 

ИСХОДНИК РЕЗУЛЬТАТ

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

abc,cde,ef,gh,mn,test,ss, df,fw,ewe,wwe abc, cde, df, ef, ewe, fw, gh, mn, ss, test, wwe

 

Комментарий:

С помощью регулярного выражения и цикла проходим по строке до тех пор, пока встречается разделительный символ (‘,’) и выводим каждую новую подстроку в новой строке Regexp_Substr('abc,cde,ef,gh,mn,test,ss,df,fw,ewe,wwe', '[^,]+', 1, Level)

Сортируем полученный столбец по возрастанию ORDER BY 1 в Т

Сборка столбика в строчку будет производиться с помощью функции Sys_Connect_By_Path(Str, ', ')

 

18. Имеется таблица с двумя столбцами – дочерняя вершина и родительская вершина. Определить наборы вершин, образующих связанные множества. Например, для таблицы:

Дочерняя вершина Родительская вершина
   
   
   
   
   

результат должен быть

Связанные множества
1,2,3,4,5
6,7

 

Create Table Tab1(Child_Number Number(7,0),Parent_Number Number(7,0));

Insert Into Tab1 Values(1,2);

Insert Into Tab1 Values(2,4);

Insert Into Tab1 Values(4,5);

Insert Into Tab1 Values(4,3);

Insert Into Tab1 Values(6,7);

With

Tmp As

(Select Ch, Ch||Sys_Connect_By_Path(Parent_Number, ',') Str

from (select * from (select connect_by_root(Child_Number) Ch, Parent_Number

From Tab1

Connect By Prior Parent_Number = Child_Number

Order By 1)

Where Ch Not In

(Select Parent_Number From (Select Connect_By_Root(Child_Number) Ch, Parent_Number

From Tab1

Connect By Prior Parent_Number = Child_Number

Order By 1))

)

Connect By Prior Ch = Ch

And Prior Parent_Number<Parent_Number)

 

Select Str "Связанные множества" From Tmp

Where (Ch, Length(Str)) In (Select Ch, Max(Length(Str)) From Tmp Group By Ch)


Результат:

Комментарий:

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

В Tab1 (CONNECT_BY_ROOT - унарный оператор, который верен только в иерархических запросах. Когда вы указываете колонку с этим оператором, то Oracle возвращает значение колонки используя данные их корневой строки.

Ставим условие, что дочернее значение Сh не может быть равно родительскому значению.)

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

 

19. Определить список последовательностей подчиненности от преподавателей, не имеющих начальника, до преподавателей, не имеющих подчиненных. Результат представить в виде:

Костыркин-> Викулина-> Студейкин->Соколов (не имеет подчиненных)

 

With List As (Select Rownum X,Level Y, Ltrim(Sys_Connect_By_Path(Фамилия, '->'),'->') Phraze

From Преподаватели

Where Level >= 2

Start With Подчиняется Is Null

Connect By Prior Номер_Преподавателя = Подчиняется

Order By Rownum)

 

Select A1.Phraze || ' (не имеет подчинённых)' "RESULT"

From

List a1

Full Join

List A2

On A1.X+1 = A2.X

Where A1.Y >= A2.Y Or A2.Y Is Null

Order By "RESULT";

 

Комментарий:

Здесь подзапрос List, который выводит иерархию преподавателей, начиная с преподавателя, который никому не подчиняется. В данной выборке присутствуют столбцы rownum X и level Y, добавленные для того, чтобы по rownum x можно было объединить одинаковые таблицы A1 и A2, а по level Y я брал максимально возможный уровень, отсекая при этом промежуточные результаты.

 

Связь дает результат: откуда при помощи Where мы выбираем нужное

RESULT

Абдулов->Загарийчук->Позднякова (не имеет подчинённых)

Абдулов->Студейкин (не имеет подчинённых)

Абдулов->Тарасова (не имеет подчинённых)

Костыркин->Викулина->Соколов->Казанко (не имеет подчинённых)

 

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

 

Select Фамилия,Зарплата,

Round(Ratio_To_Report(Зарплата) Over (Partition By Кафедра),3)*100 "%"

From Преподаватели;

 

Комментарий:

Функция подсчета долей(Ratio_To_Report) позволяет одной SQL-операцией получить для каждой строки ее "вес" в таблице в соответствии с ее значениями

 

ФАМИЛИЯ ЗАРПЛАТА %

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

Казанко 2000 19

Соколов 1500 14,3

Викулина 3000 28,6

Костыркин 4000 38,1

Позднякова 2500 20,8

Загарийчук 2000 16,7

Студейкин 2500 20,8

Тарасова 2000 16,7

Абдулов 3000 25

 

9 rows selected

 


ВАРИАНТ 23

(Базы данных HR и OE)

1. Имеется таблица с числовым столбцом первичного ключа, например:

ID

Для каждого значения ID получить набор значений в виде "горки":

ID Rezult
   
  1,3,1
  1,3,6,3,1
  1,3,6,8,6,3,1
  1,3,6,8,9,8,6,3,1
  1,3,6,8,9,11,9,8,6,3,1

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

 

Вариант 1

select ID, nvl2(a7,a7||',','')||nvl2(a6,a6||',','')||nvl2(a5,a5||',','')||nvl2(a4,a4||',','')

||nvl2(a3,a3||',','')||nvl2(a2,a2||',','')||nvl2(a1,a1,'')||nvl2(a2,','||a2,'')||nvl2(a3,','||a3,'')

||nvl2(a4,','||a4,'')||nvl2(a5,','||a5,'')||nvl2(a6,','||a6,'')||nvl2(a7,','||a7,'') as Result

from

(select pp.id ID, a1,a2,a3,a4,a5,a6,a7

from (select a1,a2,a3,a4,a5,a6,a7,rownum r2

from

(select distinct p1.ID a1, p2.ID a2, p3.ID a3, p4.ID a4, p5.ID a5, p6.ID a6, p7.ID a7

from

PkId p1 left join PkId p2 on p2.ID < p1.ID

left join PkId p3 on p3.ID < p2.ID

left join PkId p4 on p4.ID < p3.ID

left join PkId p5 on p5.ID < p4.ID

left join PkId p6 on p6.ID < p5.ID

left join PkId p7 on p7.ID < p6.ID

order by p1.ID, p2.ID, p3.ID, p4.ID, p5.ID, p6.ID, p7.ID)) ps

right join

(select Id, rownum r1 from pkId) pp

on Pp.Id = ps.a1 and ps.r2 = power(2,pp.r1-1))

 

Вариант 2

select tab1.id, str1||str2 as "Result" from

(select id, LTRIM(SYS_CONNECT_BY_PATH(id, ','), ',') str1, rownum R1

from

(select id, rownum r2 from PkID)

start with r2 = 1

connect by prior r2 = r2 - 1) tab1

left join

(select id, ltrim(ltrim(SYS_CONNECT_BY_PATH(id, ','), ','), '0987654321') str2, rownum R2

from

(select id, rownum r2 from PkID)

where id = 1

start with r2 = r2

connect by r2 = prior r2 - 1) tab2

on tab1.R1 = tab2.R2

 

Вариант 1

ID RESULT

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

1 1

3 1,3,1

6 1,3,6,3,1

8 1,3,6,8,6,3,1

9 1,3,6,8,9,8,6,3,1

11 1,3,6,8,9,11,9,8,6,3,1

23 1,3,6,8,9,11,23,11,9,8,6,3,1

 

7 rows selected

 

Комментарий:

1) создаем таблицу PkId как в примере

2) соединяем ее саму с собой шесть раз по условию, что значение в присоединяемой таблице меньше чем в текущей, чем обеспечиваем убываемость значений в строках по столбцам. Будем называть ее Ps

3) выбираем значения ID и всех столбцов Ps таблицы. Путем соединения PkId с Ps таблицей по условию равенства Id в Ps и Id в PkId и по условию зависимости номеров строк(в Ps нужная строка будет находится как 2 в степени номера строки PkId)

4) выбираем столбец Id и Result

 

Вариант 2

ID Result

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

1 1

3 1,3,1

6 1,3,6,3,1

8 1,3,6,8,6,3,1

9 1,3,6,8,9,8,6,3,1

11 1,3,6,8,9,11,9,8,6,3,1

23 1,3,6,8,9,11,23,11,9,8,6,3,1

55 1,3,6,8,9,11,23,55,23,11,9,8,6,3,1

 

8 rows selected

 

Комментарий:

1) Первый подзапрос выводит с помощью иерархии путь от корня до текущего значения

2) Второй подзапрос выводит в обратном порядке без первого значения

3) Select str1||str2 выводит конкатенацию строк из первого и второго подзапросов

 

2. Создать запрос для определения произведения количеств сотрудников в отделах.

 

select round(exp(sum(ln(ID)))) as composition

from (select count(employee_id) as "ID"

from employees

group by department_id);

 

COMPOSITION

-----------

 

Комментарий:

1) Подзапрос select count(employee_id) as "ID"

from employees

group by department_id

выводит таблицу с количествами сотрудников в отделах без вывода отделов, к которым они относятся. Обозначим столбец как ID

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

Сумма логарифмов каждой строки sum(ln(ID)) – логарифм произведения строк

Экспонента в степени этого логарифма exp(sum(ln(ID))) – произведение строк подзапроса

3) Усечем до целого, так как exp(sum(ln(ID)) возвращает значение со знаками после запятой.

 

3. Имеется стандартная шахматная доска 8 х 8 = 64 клетки.

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

То есть два ферзя не могут находиться ни на одной горизонтали, ни на одной вертикали, ни на одной диагонали.

Требуется одной командой SELECT вывести все варианты решения задачи в виде (каждая строка - это один вариант решения задачи о восьми ферзях):

Столбец 1. Положение ферзя на вертикали "а" (в виде ‘aN’)

Столбец 2. Положение ферзя на вертикали "b" (в виде ‘bN’)

Столбец 3. Положение ферзя на вертикали "с" (в виде ‘cN)

Столбец 4. Положение ферзя на вертикали "d" (в виде ‘dN’)

Столбец 5. Положение ферзя на вертикали "е" (в виде ‘eN’)

Столбец 6. Положение ферзя на вертикали "f" (в виде ‘fN’)

Столбец 7. Положение ферзя на вертикали "g" (в виде ‘gN’)

Столбец 8. Положение ферзя на вертикали "h" (в виде ‘hN’)

 

Пример одного решения (одной строки результата):

A B C D E F G H
a1 b1 c1 d1 e1 f1 g1 h1

 

select 'a' || a A, 'b' || b B, 'c' || c C, 'd' || d D, 'e' || e E, 'f' || f F, 'g' || g G, 'h' || h H

from

(

select a, b, c, d, e, f, g, h,

case when a = b or abs(a - b) = 1 or a = c or abs(a - c) = 2 or a = d or abs(a - d) = 3 or a = e or abs(a - e) = 4 or a = f or abs(a - f) = 5 or a = g or abs(a - g) = 6 or a = h or abs(a - h) = 7

then 0

else case when b = c or abs(b - c) = 1 or b = d or abs(b - d) = 2 or b = e or abs(b - e) = 3 or b = f or abs(b - f) = 4 or b = g or abs(b - g) = 5 or b = h or abs(b - h) = 6

then 0

else case when c = d or abs(c - d) = 1 or c = e or abs(c - e) = 2 or c = f or abs(c - f) = 3 or c = g or abs(c - g) = 4 or c = h or abs(c - h) = 5

then 0

else case when d = e or abs(d - e) = 1 or d = f or abs(d - f) = 2 or d = g or abs(d - g) = 3 or d = h or abs(d - h) = 4

then 0

else case when e = f or abs(e - f) = 1 or e = g or abs(e - g) = 2 or e = h or abs(e - h) = 3

then 0

else case when f = g or abs(f - g) = 1 or f = h or abs(f - h) = 2

then 0

else case when g = h or abs(g - h) = 1

then 0

else 1

end

end

end

end

end

end

end Bool

from

(select level a from dual connect by level <= 8)

cross join

(select level b from dual connect by level <= 8)

cross join

(select level c from dual connect by level <= 8)

cross join

(select level d from dual connect by level <= 8)

cross join

(select level e from dual connect by level <= 8)

cross join

(select level f from dual connect by level <= 8)

cross join

(select level g from dual connect by level <= 8)

cross join

(select level h from dual connect by level <= 8)

)

where Bool = 1;

 

A B C D E F G H

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

a4 b2 c7 d3 e6 f8 g5 h1

a5 b7 c2 d6 e3 f1 g4 h8

 

92 rows selected

Комментарий:

1) создаем запрос select level a from dual connect by level <= 8

который выдает числа от 1 до 8:

2) делаем cross join 8 таких столбцов

(select level a from dual connect by level <= 8)

cross join

(select level b from dual connect by level <= 8)

cross join

(select level c from dual connect by level <= 8)

cross join

(select level d from dual connect by level <= 8)

cross join

(select level e from dual connect by level <= 8)

cross join

(select level f from dual connect by level <= 8)

cross join

(select level g from dual connect by level <= 8)

cross join

(select level h from dual connect by level <= 8)

)

Как результат – таблица вариантов расположения ферзей, где ферзи не могут находится на одной вертикали

3) далее вложенными case удаляем варианты расположения ферзей на одной горизонтали и диагонали, т.е. выбираем столбец, который содержит 1, если строка соответствует нашим ограничениям и 0, если нет.

как пример: case when e = f or abs(e - f) = 1 or e = g or abs(e - g) = 2 or e = h or abs(e - h) = 3

then 0 – возвращение 0, если значение в е совпадает с f, или g, или h (это удаляет варианты расположения на одной горизонтали), а также

e = f +- 1 или e = g +- 1 e = h +- 1 (это удаляет варианты расположения на одной диагонали)

4) выводим получившиеся столбцы:

select a, b, c, d, e, f, g, h,

case when a = b or abs(a - b) = 1 or a = c or abs(a - c) = 2 or a = d or abs(a - d) = 3 or a = e or abs(a - e) = 4 or a = f or abs(a - f) = 5 or a = g or abs(a - g) = 6 or a = h or abs(a - h) = 7


Дата добавления: 2015-08-18; просмотров: 132 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Main_Table PK User_Constraints 21 страница| Main_Table PK User_Constraints 23 страница

mybiblioteka.su - 2015-2024 год. (0.077 сек.)