powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Сертификация и обучение [игнор отключен] [закрыт для гостей] / Оценка уровня ПОНИМАНИЯ sql
22 сообщений из 22, страница 1 из 1
Оценка уровня ПОНИМАНИЯ sql
    #35285696
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Уважаемые коллеги! Предлагаю вам на рассмотрение задачу, решение которой на соответствующем уровне позволяет оценить уровень ПОНИМАНИЯ sql.

Задача:
Есть таблица dwh (id int, pos varchar(50), vl int).
Значения в поле id уникальны, но не последовательны(например -20,-15,5 ...).
В поле name наименования позиций (уникальные).
В поле vl количество единиц по соответствующей позиции.
Для любого vl справедливо, что vl <= квадрата количества записей в таблице dwh.
Пример данных:
Код: plaintext
1.
2.
3.
4.
5.
6.
 
id         pos            vl
-20	сервер           3
-15	Монитор          5
  5	Системный блок   3
 10	Кондиционер      2

Напишите скрипт, возвращающий select, в котором каждой позиции соответствует
количество строк, равное значению поля vl. Поля результата:
np - номер позиции в списке наименований позиций, отсортированных по алфавиту (1,2,3...)
nr - последовательня нумерация строк внутри одной позиции
pos - наименование позиции.

Пример результата:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
np         nr           pos
1	1	Кондиционер
1	2	Кондиционер
2	1	Монитор
2	2	Монитор
2	3	Монитор
2	4	Монитор
2	5	Монитор
3	1	сервер
3	2	сервер
3	3	сервер
4	1	Системный блок
4	2	Системный блок
4	3	Системный блок


!!! Решите задачу в рамках ограничений нужного уровня (см. ниже)

Уровни:
1: задача решена более чем 3 запросами sql
2: задача решена 3 запросами sql
3: задача решена 1 запросом sql вложенными запросами/подзапросами
4: задача решена 1 запросом sql без вложенных запросов/подзапросов
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35289208
Вот мое решение:
SELECT ROW_NUMBER () OVER (ORDER BY t2.pos) np,
ROW_NUMBER () OVER (PARTITION BY t2.pos ORDER BY t2.pos) nr,
t2.pos, t2.vl
FROM (SELECT DISTINCT LEVEL, t.*
FROM dwh t CONNECT BY LEVEL <= t.vl) t2;
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35294195
SemenovAL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дяденька а скажито пожалуйста, А ответы укладываются в стандарт SQL92?, или можно жульничать на PL/SQL?
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35303237
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Приношу извинения за задержку с ответами. Последнее время не получается посещать этот форум так часто, как хочется.

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

Предлагаю следущие уточнения:

1 и 2 варианты - "жульничаем"
3 и 4 варианты - используем возможности исключительно SQL-92


P.S. SemenovALДяденька а скажито пожалуйста, А

Пожалуйста!
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35303262
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
P.P.S. " жульничаем " - PL/SQ L или TSQL
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35306250
SemenovAL
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
млн. посетительВот мое решение:
SELECT ROW_NUMBER () OVER (ORDER BY t2.pos) np,
ROW_NUMBER () OVER (PARTITION BY t2.pos ORDER BY t2.pos) nr,
t2.pos, t2.vl
FROM (SELECT DISTINCT LEVEL, t.*
FROM dwh t CONNECT BY LEVEL <= t.vl) t2;

немного не то что просили
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 1 	 1 	hup	 2 
 2 	 2 	hup	 2 
 3 	 1 	monitor	 5 
 4 	 2 	monitor	 5 
 5 	 3 	monitor	 5 
 6 	 4 	monitor	 5 
 7 	 5 	monitor	 5 
 8 	 1 	server	 3 
 9 	 2 	server	 3 
 10 	 3 	server	 3 
 11 	 1 	sys block	 3 
 12 	 2 	sys block	 3 
 13 	 3 	sys block	 3 

Народ гляжу не очень заинтересовался топиком, а вот мне как новечку было бы очень любопытно взглянуть на Ваши решения товариши гуроны.
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35375362
junior_oracle
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
учитывая результат млн. посетитель
Код: plaintext
1.
2.
3.
4.
5.
SELECT
  DISTINCT(level), row_num, t.pos
FROM (SELECT rownum row_num, pos, vl FROM dwh) t
CONNECT BY level <= t.vl
ORDER BY row_num
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35382893
Фотография newby2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sql_msЗначения в поле id уникальны, но не последовательны(например -20,-15,5 ...).разве это нужно явно упоминать? по-моему это и так подразумеватся...
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35445086
raul_83
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Без использования иерархии и row_number
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
SELECT * INTO #test FROM
(
SELECT - 20  as id, 'сервер' as pos, 3  as vl
UNION 
SELECT - 15 , 'монитор', 5 
UNION 
SELECT  5 , 'системный блок', 3 
UNION 
SELECT  10 , 'кондиционер', 2 
) z 


select np,nr,pos
from #test a
join 
(
		SELECT a.id,count(*) as np 
		from #test a
		join #test b on a.pos>=b.pos
		group by a.id
	) b ON a.id = b.id
JOIN 
(
	select max_count*a.np+b.np+ 1  as nr
	from
	(
		SELECT a.id,count(*)- 1  as np 
		from #test a
		join #test b on a.pos>=b.pos
		group by a.id
	) a 
	cross join 
	(
		SELECT a.id,count(*)- 1  as np 
		from #test a
		join #test b on a.pos>=b.pos
		group by a.id
	) b
	cross join 
	(
		select count(*) as max_count from #test
	)c
) c ON a.vl>=c.nr
order by  1 , 2  
	
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35519114
C#C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql_ms4: задача решена 1 запросом sql без вложенных запросов/подзапросовMS 2005
Код: plaintext
1.
2.
3.
4.
5.
select 
dense_rank()over(order by pos) np,
row_number()over(partition by pos order by pos) nr, pos
from dwh join master..spt_values
on (type = 'P' and number < vl)
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35528383
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
raul_83
Код: plaintext
Без использования иерархии и row_number 
- решение 3 уровня (все верно, кроме 1 лишний join на #test a)

C#C++ sql_ms4: задача решена 1 запросом sql без вложенных запросов/подзапросовMS 2005
Код: plaintext
1.
2.
3.
4.
5.
select 
dense_rank()over(order by pos) np,
row_number()over(partition by pos order by pos) nr, pos
from dwh join master..spt_values
on (type = 'P' and number < vl)
- решение 2 уровня , так как SQL-92 не предусматривает наличие таких таблицы и функций
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35528730
C#C++
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
sql_ms - решение 2 уровня , так как SQL-92 не предусматривает наличие таких таблицы и функцийПонятно.
Тогда можно смело утверждать, что 4 уровень недостижим. На SQL-92 далеко не уедешь...
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35528913
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
C#C++ sql_ms - решение 2 уровня , так как SQL-92 не предусматривает наличие таких таблицы и функцийПонятно.
Тогда можно смело утверждать, что 4 уровень недостижим. На SQL-92 далеко не уедешь...

4 уровень - решение есть.
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533110
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
WITH
dwh AS (
  SELECT - 20  id, 'сервер' pos,  3  vl FROM dual UNION
  SELECT - 15 , 'монитор',  5  FROM dual UNION
  SELECT  5 , 'системный блок',  3  FROM dual UNION
  SELECT  10 , 'кондиционер',  2  FROM dual
)
SELECT
  a.pos,COUNT(distinct b.pos) as np,COUNT(*)/COUNT(distinct b.pos) nr
FROM
  dwh c1
  CROSS JOIN dwh c2
  CROSS JOIN dwh c3
  CROSS JOIN dwh c4
  CROSS JOIN dwh a
  CROSS JOIN dwh b
WHERE
  c1.id||c2.id <= c3.id||c4.id AND
  a.pos >= b.pos
GROUP BY
  c1.id||c2.id,a.pos
HAVING
  COUNT(*)/COUNT(distinct b.pos) <= MAX(a.vl)
ORDER BY
  np,nr;
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533154
извращенец
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
WITH
dwh AS (
  SELECT - 20  id, 'сервер' pos,  3  vl FROM dual UNION
  SELECT - 15 , 'монитор',  5  FROM dual UNION
  SELECT  5 , 'системный блок',  3  FROM dual UNION
  SELECT  10 , 'кондиционер',  2  FROM dual
)
SELECT
  a.pos,COUNT(distinct b.pos) as np,COUNT(*)/COUNT(distinct b.pos) nr
FROM
  dwh c1
  CROSS JOIN dwh c2
  CROSS JOIN dwh c3
  CROSS JOIN dwh c4
  CROSS JOIN dwh a
  CROSS JOIN dwh b
WHERE
  c1.id||c2.id <= c3.id||c4.id AND
  a.pos >= b.pos
GROUP BY
  c1.id||c2.id,a.pos
HAVING
  COUNT(*)/COUNT(distinct b.pos) <= MAX(a.vl)
ORDER BY
  np,nr;


Почти всё хорошо, но ты попал на магию данных :)
Попробуй свой запрос на таком наборе данных:
Код: plaintext
1.
2.
3.
4.
5.
6.
WITH
dwh AS (
  SELECT - 20  id, 'сервер' pos,  3  vl FROM dual UNION
  SELECT - 15 , 'монитор',  5  FROM dual UNION
  SELECT  1 , 'системный блок',  3  FROM dual UNION
  SELECT  11 , 'кондиционер',  2  FROM dual
)
:)
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533354
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
WITH
dwh AS (
  SELECT - 20  id, 'сервер' pos,  3  vl FROM dual UNION
  SELECT - 15 , 'монитор',  5  FROM dual UNION
  SELECT  1 , 'системный блок',  3  FROM dual UNION
  SELECT  11 , 'кондиционер',  2  FROM dual
)
SELECT
  a.pos,COUNT(distinct b.pos) as np,COUNT(*)/COUNT(distinct b.pos) nr
FROM
  dwh c1
  CROSS JOIN dwh c2
  CROSS JOIN dwh c3
  CROSS JOIN dwh c4
  CROSS JOIN dwh a
  CROSS JOIN dwh b
WHERE
  c1.id||'#'||c2.id <= c3.id||'#'||c4.id AND
  a.pos >= b.pos
GROUP BY
  c1.id||'#'||c2.id,a.pos
HAVING
  COUNT(*)/COUNT(distinct b.pos) <= MAX(a.vl)
ORDER BY
  np,nr;
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533557
извращенец
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
WITH
dwh AS (
  SELECT - 20  id, 'сервер' pos,  3  vl FROM dual UNION
  SELECT - 15 , 'монитор',  5  FROM dual UNION
  SELECT  1 , 'системный блок',  3  FROM dual UNION
  SELECT  11 , 'кондиционер',  2  FROM dual
)
SELECT
  a.pos,COUNT(distinct b.pos) as np,COUNT(*)/COUNT(distinct b.pos) nr
FROM
  dwh c1
  CROSS JOIN dwh c2
  CROSS JOIN dwh c3
  CROSS JOIN dwh c4
  CROSS JOIN dwh a
  CROSS JOIN dwh b
WHERE
  c1.id||'#'||c2.id <= c3.id||'#'||c4.id AND
  a.pos >= b.pos
GROUP BY
  c1.id||'#'||c2.id,a.pos
HAVING
  COUNT(*)/COUNT(distinct b.pos) <= MAX(a.vl)
ORDER BY
  np,nr;

Уже совсем хорошо, но можно сделать с пятью обращениями к таблице, а не с шестью, как это сделано сейчас. :)
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533621
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
извращенец
Код: plaintext
1.
2.
WITH
dwh AS ...
- все верно - 4 уровень



Добрый Э - Эх извращенец+
Код: plaintext
1.
2.
WITH
dwh AS ...

Уже совсем хорошо, но можно сделать с пятью обращениями к таблице, а не с шестью, как это сделано сейчас. :) - приведите, пожалуйста, ваше решение.
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533689
sql_ms
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну и бонус -условие решения задачи для 5 уровня.

5 уровень: Решить эту задачу для неуникальных сочетаний (id, pos, vl) или аргументировано доказать, что это невозможно


p.s.

Уровень 4+: Решить задачу для неуникальных pos , не объединяя одинаковые pos в одну и не используя сложение строк.

p.p.s

Надеюсь, Вам было интересно.
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533865
sql_ms приведите, пожалуйста, ваше решение.
Ну, назвать такого уродца решением - язык не поворачивается...
Но если сильно интересно, то вот:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
with dwh as (select - 20  id, 'сервер' pos,  3  vl from dual union all
             select - 15 , 'монитор',  5  from dual union all
             select  5 , 'системный блок',  3  from dual union all
             select  10 , 'кондиционер',  14  from dual union all
             select  15 , 'клава',  3  from dual
            )
select count(case when t1.pos >= t2.pos then t1.pos end)/count(distinct t2.pos) as np,
       (count(case when t1.pos >= t2.pos and t3.pos >= t4.pos then  1  end)/
       (count(case when t1.pos >= t2.pos then t1.pos end)/count(distinct t2.pos)) -  1 ) *
       count(distinct t2.pos) + count(distinct case when t5.pos >= t2.pos and t5.pos >= t4.pos then t2.pos end) nr,
       t1.pos, t1.id, t1.vl
  from dwh t1
 cross join dwh t2
 cross join dwh t3
 cross join dwh t4
 cross join dwh t5
 group by t1.id, t1.pos, t1.vl, t3.id, t5.id
having t1.vl >= (count(case when t1.pos >= t2.pos and t3.pos >= t4.pos then  1  end)/
       (count(case when t1.pos >= t2.pos then t1.pos end)/count(distinct t2.pos)) -  1 ) *
       count(distinct t2.pos) + count(distinct case when t5.pos >= t2.pos and t5.pos >= t4.pos then t2.pos end)
order by np, nr


И результат его работы:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
NP   NR       POS           ID   VL
--   --   --------------   ---   --
  1      1    клава              15      3  
  1      2    клава              15      3  
  1      3    клава              15      3  
  2      1    кондиционер        10     14  
  2      2    кондиционер        10     14  
  2      3    кондиционер        10     14  
  2      4    кондиционер        10     14  
  2      5    кондиционер        10     14  
  2      6    кондиционер        10     14  
  2      7    кондиционер        10     14  
  2      8    кондиционер        10     14  
  2      9    кондиционер        10     14  
  2     10    кондиционер        10     14  
  2     11    кондиционер        10     14  
  2     12    кондиционер        10     14  
  2     13    кондиционер        10     14  
  2     14    кондиционер        10     14  
  3      1    монитор          - 15      5  
  3      2    монитор          - 15      5  
  3      3    монитор          - 15      5  
  3      4    монитор          - 15      5  
  3      5    монитор          - 15      5  
  4      1    сервер           - 20      3  
  4      2    сервер           - 20      3  
  4      3    сервер           - 20      3  
  5      1    системный блок      5      3  
  5      2    системный блок      5      3  
  5      3    системный блок      5      3  

 28  row(s) retrieved
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533872
sql_msНу и бонус -условие решения задачи для 5 уровня.

5 уровень: Решить эту задачу для неуникальных сочетаний (id, pos, vl) или аргументировано доказать, что это невозможно


p.s.

Уровень 4+: Решить задачу для неуникальных pos , не объединяя одинаковые pos в одну и не используя сложение строк.

p.p.s

Надеюсь, Вам было интересно.
Про 4+ - не совсем понял задания... :(
ID при этом остается уникальным?
Что значит - не объединяя одинаковые pos и не используя сложения строк?
...
Рейтинг: 0 / 0
Оценка уровня ПОНИМАНИЯ sql
    #35533940
Если все правильно понял, то 4+ это примерно такое:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
with dwh as (select - 20  id, 'сервер' pos,  3  vl from dual union all
             select - 15 , 'монитор',  5  from dual union all
             select  5 , 'системный блок',  3  from dual union all
             select - 10 , 'кондиционер',  4  from dual union all
             select  15 , 'кондиционер',  2  from dual
            )
select count(case when (t1.pos > t2.pos or t1.pos = t2.pos and t1.id >= t2.id) then t1.id end)/count(distinct t2.id) as np,
       
       (count(case when (t1.pos > t2.pos or t1.pos = t2.pos and t1.id >= t2.id) 
                    and (t3.pos > t4.pos or t3.pos = t4.pos and t3.id >= t4.id) then  1  end)/
       (count(case when (t1.pos > t2.pos or t1.pos = t2.pos and t1.id >= t2.id) then t1.id end)/count(distinct t2.id)) -  1 ) *
       count(distinct t2.id) + count(distinct case when 
                        (t5.pos > t2.pos or t5.pos = t2.pos and t5.id >= t2.id) 
                    and (t5.pos > t4.pos or t5.pos = t4.pos and t5.id >= t4.id) then t2.id end) nr,
       
       t1.pos, t1.id, t1.vl
  from dwh t1
 cross join dwh t2
 cross join dwh t3
 cross join dwh t4
 cross join dwh t5
 group by t1.id, t1.pos, t1.vl, t3.id, t5.id
having t1.vl >= (count(case when (t1.pos > t2.pos or t1.pos = t2.pos and t1.id >= t2.id) 
                    and (t3.pos > t4.pos or t3.pos = t4.pos and t3.id >= t4.id) then  1  end)/
       (count(case when (t1.pos > t2.pos or t1.pos = t2.pos and t1.id >= t2.id) then t1.id end)/count(distinct t2.id)) -  1 ) *
       count(distinct t2.id) + count(distinct case when 
                        (t5.pos > t2.pos or t5.pos = t2.pos and t5.id >= t2.id) 
                    and (t5.pos > t4.pos or t5.pos = t4.pos and t5.id >= t4.id) then t2.id end)
order by np, nr

Query finished, retrieving results...

NP   NR        POS          ID   VL
--   --   --------------   ---   --
  1      1    кондиционер      - 10      4  
  1      2    кондиционер      - 10      4  
  1      3    кондиционер      - 10      4  
  1      4    кондиционер      - 10      4  
  2      1    кондиционер        15      2  
  2      2    кондиционер        15      2  
  3      1    монитор          - 15      5  
  3      2    монитор          - 15      5  
  3      3    монитор          - 15      5  
  3      4    монитор          - 15      5  
  3      5    монитор          - 15      5  
  4      1    сервер           - 20      3  
  4      2    сервер           - 20      3  
  4      3    сервер           - 20      3  
  5      1    системный блок      5      3  
  5      2    системный блок      5      3  
  5      3    системный блок      5      3  

 17  row(s) retrieved
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / Сертификация и обучение [игнор отключен] [закрыт для гостей] / Оценка уровня ПОНИМАНИЯ sql
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]