Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.05.2013, 12:34   #1
Chugun
Пользователь
 
Регистрация: 04.02.2009
Сообщений: 30
По умолчанию объединить SELECT'ы в столбцы

Доброго, уважаемые форумчане.
прошу помощи
SQL только начал изучать и вопросов очень много
многое делаю бестолково, неправильно и т.п.

вопрос вот в чём:
у меня есть две конструкции "SELECT ... UNION ALL SELECT ..."
результатом которых являются столбцы строк вида:
Код:
Секция1
Иванов Иван Иванович
Петров Петр Петрович
Сидоров Сидр Сидорович
нужно сделать чтобы было примерно так:
Код:
------------------------------------------------------
столбец 1                     | столбец 2
------------------------------------------------------
Секция1                       | Секция2
Иванов Иван Иванович   | Иванов Иван Иванович
Петров Петр Петрович    | Пупкин Василий Федорович
Сидоров Сидр Сидорович| Петров Петр Петрович
можно ли как-то совершить сие?
Chugun вне форума Ответить с цитированием
Старый 29.05.2013, 13:06   #2
eval
Подтвердите свой е-майл
 
Регистрация: 29.08.2012
Сообщений: 4,022
По умолчанию

Откуда пупкин взялся?
eval вне форума Ответить с цитированием
Старый 29.05.2013, 13:09   #3
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,515
По умолчанию

чисто теоретически, да можно
Код:
select sector1.* , sector2.*
from ( select ... ) as sector1
<?full?> join (select ....) as sector2 on sector1.<???> = sector2.<????>
но для практики надо придумать что будет вместо <???>
как вариант "придумки"

На мой взгляд этим (разбиением на колонки, сначала две, потом три, четыре,...) должны заниматься программы "визуализации" (то бишь клиенты), но не СУБД(сервер).
тем более когда в колонках НЕТ логичной (на основе данных хранящихся в БД) связи строк.
Цитата:
но для практики надо придумать что будет вместо <???>
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 29.05.2013, 13:14   #4
Chugun
Пользователь
 
Регистрация: 04.02.2009
Сообщений: 30
По умолчанию

Цитата:
Сообщение от eval Посмотреть сообщение
Откуда пупкин взялся?
по результатам второго SELECT'a
чтобы устранить вопросы подобного рода, вот код этих самых селектов
Код:
;WITH TMP (SNAME,SC) AS
(
	SELECT S.S_NAME, COUNT(P_ID) 
		FROM SOSTAV_SEKCIY SS
			INNER JOIN SEKCIYA S ON S.S_NAME=SS.S_NAME
		GROUP BY S.S_NAME
)
SELECT SNAME AS 'Непопулярные секции' 
	FROM TMP 
	WHERE SC=(SELECT MIN(SC) FROM TMP)
UNION ALL
	SELECT T.T_S_NAME + ' ' + T.T_F_NAME + ' ' + T.T_OTCH
	FROM  RASPISANIE_SEKCIY RS 
		INNER JOIN TEACHERS T ON T.T_ID=RS.T_ID
		INNER JOIN TMP ON TMP.SNAME=RS.S_NAME
	WHERE TMP.SC=(SELECT MIN(SC) FROM TMP)
	GROUP BY RS.T_ID,RS.S_NAME,T.T_S_NAME,T.T_F_NAME,T.T_OTCH
Код:
;WITH TMP (SNAME,SC) AS
(
	SELECT S.S_NAME, COUNT(P_ID) 
		FROM SOSTAV_SEKCIY SS
			INNER JOIN SEKCIYA S ON S.S_NAME=SS.S_NAME
		GROUP BY S.S_NAME
)
SELECT SNAME AS 'Популярные секции'
	FROM TMP 
	WHERE SC=(SELECT MAX(SC) FROM TMP)
UNION ALL
SELECT T.T_S_NAME + ' ' + T.T_F_NAME + ' ' + T.T_OTCH
	FROM  RASPISANIE_SEKCIY RS 
		INNER JOIN TEACHERS T ON T.T_ID=RS.T_ID
		INNER JOIN TMP ON TMP.SNAME=RS.S_NAME
	WHERE TMP.SC=(SELECT MAX(SC) FROM TMP)
	GROUP BY RS.T_ID,RS.S_NAME,T.T_S_NAME,T.T_F_NAME,T.T_OTCH
как видите, отличаются они не многим (а именно: один - минимум, второй - максимум)
вот создание таблиц:
Код:
CREATE TABLE PUPILS
(
	P_ID	INTEGER	NOT NULL	PRIMARY KEY,
	P_S_NAME	VARCHAR(32)	NOT NULL,
	P_F_NAME	VARCHAR(32)	NOT NULL,
	P_OTCH	VARCHAR(32),
	P_B_DAY DATETIME	NOT NULL,
	P_ADDRESS	VARCHAR(100)	NOT NULL,
	P_TEL	VARCHAR(12)
)
GO

CREATE TABLE SEKCIYA
(
	S_NAME	VARCHAR(32)	NOT NULL	PRIMARY KEY,
	S_ADDRESS VARCHAR(100)
)
GO

CREATE TABLE TEACHERS
(
	T_ID	INTEGER	NOT NULL	PRIMARY KEY,
	T_S_NAME	VARCHAR(32)	NOT NULL,
	T_F_NAME	VARCHAR(32)	NOT NULL,
	T_OTCH	VARCHAR(32),
	T_SPEC	VARCHAR(32)	NOT NULL,
	T_RAZR	INT	NOT NULL CHECK (T_RAZR > 0),
	T_ADDRESS	VARCHAR(100)	NOT NULL,
	T_TEL	VARCHAR(12),
	T_JOB	DATETIME	NOT NULL	CHECK (T_JOB > '01/01/1990')
)
GO

CREATE TABLE RASPISANIE_SEKCIY
(
	T_ID	INTEGER	NOT NULL	REFERENCES TEACHERS(T_ID),
	S_NAME	VARCHAR(32)	NOT NULL	REFERENCES SEKCIYA(S_NAME),
	PRIMARY	KEY	(T_ID,S_NAME),
	S_T_DATETIME	DATETIME	NOT NULL	
)
GO

CREATE TABLE SOSTAV_SEKCIY
(
	P_ID	INTEGER	NOT NULL	REFERENCES PUPILS(P_ID),
	S_NAME	VARCHAR(32)	NOT NULL	REFERENCES SEKCIYA(S_NAME),
	PRIMARY	KEY	(P_ID,S_NAME),
	S_P_DATETIME	DATETIME	NOT NULL
)
p.s.: задание учебное, поэтому сложность его тривиальна, но ввиду отсутствия знаний и опыта в этом вопросе, я не могу его решить
Chugun вне форума Ответить с цитированием
Старый 29.05.2013, 13:22   #5
Chugun
Пользователь
 
Регистрация: 04.02.2009
Сообщений: 30
По умолчанию

Цитата:
Сообщение от evg_m Посмотреть сообщение
чисто теоретически, да можно
Код:
select sector1.* , sector2.*
from ( select ... ) as sector1
<?full?> join (select ....) as sector2 on sector1.<???> = sector2.<????>
но для практики надо придумать что будет вместо <???>
как вариант "придумки"

На мой взгляд этим (разбиением на колонки, сначала две, потом три, четыре,...) должны заниматься программы "визуализации" (то бишь клиенты), но не СУБД(сервер).
тем более когда в колонках НЕТ логичной (на основе данных хранящихся в БД) связи строк.
спасибо, дали пищу для размышлений

я думаю в каждый SELECT ввести столбец авто-заполнения, индекс, и по нему сделать связь JOIN'ом

не знаю, корректно ли выражаюсь и получится ли это...
поправьте, если что-то не так сказал
Chugun вне форума Ответить с цитированием
Старый 29.05.2013, 13:34   #6
eval
Подтвердите свой е-майл
 
Регистрация: 29.08.2012
Сообщений: 4,022
По умолчанию

Цитата:
SELECT SNAME AS 'Непопулярные секции'
FROM TMP
WHERE SC=(SELECT MIN(SC) FROM TMP)
Это что за взрыв клавиш?
Вам бы лучше вместо этой портянки галиматьи привести сюда структуру, данные и рассказать задачу, а то разбираться в этом стало скучно уже сразу
eval вне форума Ответить с цитированием
Старый 29.05.2013, 13:47   #7
Chugun
Пользователь
 
Регистрация: 04.02.2009
Сообщений: 30
Вопрос

Цитата:
Сообщение от eval Посмотреть сообщение
Это что за взрыв клавиш?
Вам бы лучше вместо этой портянки галиматьи привести сюда структуру, данные и рассказать задачу, а то разбираться в этом стало скучно уже сразу
создать БД, которая хранит информацию о занятиях в секциях спортивной школы
таблицы:
ученики
тренеры
секции
расписание занятий (тренер-секция-время)
состав секций (ученик-секция-время)

нужно найти наименее и наиболее популярные секции (популярность оценивается кол-вом учеников в секции)

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

т.е. два столбца

вышеприведённые запросы по отдельности выполняют нахождение этих самых столбцов, но как их объединить?

поправка:
преподавателем запрещено использовать любого рода переменные
Chugun вне форума Ответить с цитированием
Старый 29.05.2013, 16:14   #8
eval
Подтвердите свой е-майл
 
Регистрация: 29.08.2012
Сообщений: 4,022
По умолчанию

ну наверное как то так:
Код:
with SOSTAV_SEKCIY as
(
select 1 S_NAME, 1 S_COUNT
union all
select 2, 5
), RASPISANIE_SEKCIY as
(
select 1 P_ID, 'Иванов Иван Иванович' as P_NAME, 1 PS_NAME
union all
select 1, 'Иванов Иван Иванович', 2
union all
select 2, 'Петров Петр Петрович', 1
union all
select 2, 'Петров Петр Петрович', 2
union all
select 3, 'Сидоров Сидр Сидорович', 1
union all
select 4, 'Пупкин Василий Федорович', 2
), mins as
(
select *, row_number() over(order by p.P_ID) as num from SOSTAV_SEKCIY s
join RASPISANIE_SEKCIY p on p.PS_NAME=s.S_NAME
where s.S_COUNT=1
), maxs as
(
select *, row_number() over(order by p.P_ID) as num from SOSTAV_SEKCIY s
join RASPISANIE_SEKCIY p on p.PS_NAME=s.S_NAME
where s.S_COUNT=5
)
select mi.S_NAME, mi.P_NAME, ma.S_NAME, ma.P_NAME from mins mi
full join maxs ma on ma.num=mi.num

Последний раз редактировалось eval; 29.05.2013 в 16:17.
eval вне форума Ответить с цитированием
Старый 29.05.2013, 16:43   #9
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 19,042
По умолчанию

Про СУБД ничего не увидел, но код похож на MS SQL. Так вот, начиная с 2005-го в нем появился оператор PIVOT для подобных целей и предназначенный. Если с помощью его получится, то будет заведомо короче и изящнее. Дерзайте
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 30.05.2013, 12:19   #10
Chugun
Пользователь
 
Регистрация: 04.02.2009
Сообщений: 30
По умолчанию

Цитата:
Сообщение от eval Посмотреть сообщение
ну наверное как то так:
Код:
with SOSTAV_SEKCIY as
(
select 1 S_NAME, 1 S_COUNT
union all
select 2, 5
), RASPISANIE_SEKCIY as
(
select 1 P_ID, 'Иванов Иван Иванович' as P_NAME, 1 PS_NAME
union all
select 1, 'Иванов Иван Иванович', 2
union all
select 2, 'Петров Петр Петрович', 1
union all
select 2, 'Петров Петр Петрович', 2
union all
select 3, 'Сидоров Сидр Сидорович', 1
union all
select 4, 'Пупкин Василий Федорович', 2
), mins as
(
select *, row_number() over(order by p.P_ID) as num from SOSTAV_SEKCIY s
join RASPISANIE_SEKCIY p on p.PS_NAME=s.S_NAME
where s.S_COUNT=1
), maxs as
(
select *, row_number() over(order by p.P_ID) as num from SOSTAV_SEKCIY s
join RASPISANIE_SEKCIY p on p.PS_NAME=s.S_NAME
where s.S_COUNT=5
)
select mi.S_NAME, mi.P_NAME, ma.S_NAME, ma.P_NAME from mins mi
full join maxs ma on ma.num=mi.num
чушь полнейшая

Цитата:
Сообщение от Аватар Посмотреть сообщение
Про СУБД ничего не увидел, но код похож на MS SQL. Так вот, начиная с 2005-го в нем появился оператор PIVOT для подобных целей и предназначенный. Если с помощью его получится, то будет заведомо короче и изящнее. Дерзайте
MS SQL 2005

вчера сдал, итоговый вариант:
Код:
;WITH TMP (SNAME,SC) AS
(
	SELECT S.S_NAME , COUNT(P_ID)
		FROM SOSTAV_SEKCIY SS
			INNER JOIN SEKCIYA S ON S.S_NAME=SS.S_NAME
		GROUP BY S.S_NAME
)
SELECT 
(
	SELECT SNAME
		FROM TMP
		WHERE SC=(SELECT MIN(SC) FROM TMP)),
		(
			SELECT SNAME
				FROM TMP
				WHERE SC=(SELECT MAX(SC) FROM TMP)
		)
	UNION ALL
	SELECT a.Name, b.Name 
		FROM
		(
			SELECT ROW_NUMBER() 
				OVER (ORDER BY c.S_NAME) AS row, T_S_NAME + ' ' + T_F_NAME + ' ' + T_OTCH as Name, 
					c.S_NAME as Sec
				from TEACHERS a
					inner join RASPISANIE_SEKCIY b on a.T_ID=b.T_ID
					inner join SEKCIYA c on c.S_NAME=b.S_NAME
					inner join TMP d on c.S_NAME=d.SNAME
				where SC IN ((SELECT MIN(SC) FROM TMP)
		)
) a
FULL OUTER JOIN
(
	SELECT ROW_NUMBER() 
		OVER (ORDER BY c.S_NAME) AS row,T_S_NAME + ' ' + T_F_NAME + ' ' + T_OTCH as Name, 
			c.S_NAME as Sec
		from TEACHERS a
			inner join RASPISANIE_SEKCIY b on a.T_ID=b.T_ID
			inner join SEKCIYA c on c.S_NAME=b.S_NAME
			inner join TMP d on c.S_NAME=d.SNAME
		where SC IN ((SELECT MAX(SC) FROM TMP))
) b
ON a.row=b.row

Последний раз редактировалось Chugun; 30.05.2013 в 12:22.
Chugun вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Объединить бд 1mtn Фриланс 4 26.12.2012 17:32
Объединить 2 цикла в 1 Predator199 PHP 5 24.11.2012 13:16
Объединить 2 списка mazzahaker Помощь студентам 0 10.04.2012 15:09
Объединить программы lordseko Помощь студентам 8 22.12.2010 09:51
Объединить макросы Romuald Microsoft Office Excel 2 29.03.2009 20:09