SAP R/3 форум ABAP консультантов
Russian ABAP Developer's Club

Home - FAQ - Search - Memberlist - Usergroups - Profile - Log in to check your private messages - Register - Log in - English
Blogs - Weblogs News

SQL



 
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Talks | Беседка
View previous topic :: View next topic  
Author Message
vga
Мастер
Мастер


Age: 150
Joined: 04 Oct 2007
Posts: 1218
Location: Санкт-Петербург

PostPosted: Tue Sep 14, 2010 11:49 pm    Post subject: SQL Reply with quote

Коллеги, какие еще варианты select возможны? Пример для MySQL, но думаю всем понятно о чем речь Smile
Для примера взяты только два типа признаков (школа и институт) и их характеристики, но в реалии их может быть много. А на количество Inner Join как известно есть ограничение. Задача - написать селект, ограничивающий записи по нескольким признакам.

Code:
CREATE TABLE test (
       id INT NOT NULL AUTO_INCREMENT,
       User    VARCHAR(20) NOT NULL,
       Type    VARCHAR(20) NOT NULL,
       Value   VARCHAR(30) NULL,
       PRIMARY KEY (id)
);

CREATE INDEX test_User_Index ON test
(
       User
);

CREATE INDEX test_Type_Index ON test
(
       Type
);

CREATE INDEX test_Value_Index ON test
(
       Value
);


show index from test;


INSERT INTO test ( User, Type, Value ) VALUES ( 'Ivanov', 'School', '11' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Ivanov', 'Institute', 'MGU' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Petrov', 'School', '12' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Petrov', 'Institute', 'LKI' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Sidorov', 'School', '13' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Sidorov', 'Institute', 'LETI' );

select * from test AS t1
INNER JOIN test AS t2 ON t2.User = t1.User
where t1.User = 'Ivanov' and (t1.Type = 'School' and t1.Value = '11') and (t2.Type = 'Institute' and t2.Value = 'MGU');


_________________
Молитва - это запрос разработчику на изменение кода программы.
Back to top
View user's profile Send private message Blog Visit poster's website
Armann
Модератор
Модератор



Joined: 01 Jan 2008
Posts: 422
Location: Moscow

PostPosted: Wed Sep 15, 2010 9:50 am    Post subject: Reply with quote

Подрабатываешь? Wink
Можно например так, если я правильно понял задачу:
Code:
select * from test
where User = 'Ivanov' and Type = 'School' and Value = '11'
UNION
select * from test
where Type = 'Institute' and Value = 'MGU'

Не уверем правда что мускуль поддерживает UNION

Ну или так:
Code:
select * from test
where User = 'Ivanov' and
( ( Type = 'School' and Value = '11' ) or ( Type = 'Institute' and Value = 'MGU' ) )


Или хочется чтоб результат был в одну строчку, как в твоем примере?
Back to top
View user's profile Send private message Blog
vga
Мастер
Мастер


Age: 150
Joined: 04 Oct 2007
Posts: 1218
Location: Санкт-Петербург

PostPosted: Wed Sep 15, 2010 10:35 am    Post subject: Reply with quote

Armann wrote:
Подрабатываешь? Wink

Для души. Или скорей вспомнить, чего не знал Smile

Две строки как бы не красиво, но в случае правильного селекта можно distinct добавить, не вопрос.

В реальной жизни задача: найти всех пользователей по фильтру, например школа = 11 И институт = МГУ.

Чето мне сдается, что union и or здесь не прокатят, потому что они выберут по условию школа = 11 ИЛИ институт = МГУ.

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

_________________
Молитва - это запрос разработчику на изменение кода программы.


Last edited by vga on Wed Sep 15, 2010 10:46 am; edited 1 time in total
Back to top
View user's profile Send private message Blog Visit poster's website
vga
Мастер
Мастер


Age: 150
Joined: 04 Oct 2007
Posts: 1218
Location: Санкт-Петербург

PostPosted: Wed Sep 15, 2010 10:41 am    Post subject: Reply with quote

Во, для теста добавил. Немцы в результате не должны появиться при фильтре по Школа = 11 И Институт = МГУ.

Code:
INSERT INTO test ( User, Type, Value ) VALUES ( 'Borman', 'School', '11' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Borman', 'Institute', 'LKI' );

INSERT INTO test ( User, Type, Value ) VALUES ( 'Muller', 'School', '12' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Muller', 'Institute', 'MGU' );

INSERT INTO test ( User, Type, Value ) VALUES ( 'Shtirlitz', 'School', '11' );
INSERT INTO test ( User, Type, Value ) VALUES ( 'Shtirlitz', 'Institute', 'MGU' );


select * from test AS t1
INNER JOIN test AS t2 ON t2.User = t1.User
where (t1.Type = 'School' and t1.Value = '11') and (t2.Type = 'Institute' and t2.Value = 'MGU');

_________________
Молитва - это запрос разработчику на изменение кода программы.


Last edited by vga on Wed Sep 15, 2010 11:11 am; edited 1 time in total
Back to top
View user's profile Send private message Blog Visit poster's website
Armann
Модератор
Модератор



Joined: 01 Jan 2008
Posts: 422
Location: Moscow

PostPosted: Wed Sep 15, 2010 10:55 am    Post subject: Reply with quote

Тогда так:
Code:
select * from test as t1
where type = 'School' and value = '11'
   and exists ( select * from test as t2
                     where user = t1.user and type = 'Institute' and value = 'MGU' )

Тут правда можно натолкнуться на ограничение на количество вложенных запросов, если оно есть
Back to top
View user's profile Send private message Blog
vga
Мастер
Мастер


Age: 150
Joined: 04 Oct 2007
Posts: 1218
Location: Санкт-Петербург

PostPosted: Wed Sep 15, 2010 11:10 am    Post subject: Reply with quote

Armann wrote:
Тогда так:
Code:
select * from test as t1
where type = 'School' and value = '11'
   and exists ( select * from test as t2
                     where user = t1.user and type = 'Institute' and value = 'MGU' )

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



Ага, этот вариант рабочий!
На Inner Join тоже есть ограничение, так что может еще кто "безограничительные" варианты предложит Smile

_________________
Молитва - это запрос разработчику на изменение кода программы.
Back to top
View user's profile Send private message Blog Visit poster's website
Armann
Модератор
Модератор



Joined: 01 Jan 2008
Posts: 422
Location: Moscow

PostPosted: Wed Sep 15, 2010 12:34 pm    Post subject: Reply with quote

Еще вариант, более жесткий Smile
Code:

# Создание временной таблицы
 create temporary table tbl_tmp ...

# Заполнение временной таблицы по одному из условий
 insert into tbl_tmp
    select * from test as t1 where type = 'School' and value = '11'

# Удаление лишних данных
 delete from tbl_tmp 
    where not exist ( select * from test as t2
                     where user = t1.user and type = 'Institute' and value = 'MGU' )
# Повторять DELETE с нужными условиями до удовлетворения

Здесь потенциальное ограничение - размер временной таблицы. На время выполнения внимания не обращаем Wink
Back to top
View user's profile Send private message Blog
vga
Мастер
Мастер


Age: 150
Joined: 04 Oct 2007
Posts: 1218
Location: Санкт-Петербург

PostPosted: Wed Sep 15, 2010 4:14 pm    Post subject: Reply with quote

Ну и еще один вариант, где 2 - количество показателей, по которым должно быть совпадение. Smile

Code:
SELECT * FROM test WHERE ( Type = 'School' and Value = '11') or ( Type = 'Institute' and Value = 'MGU')
 GROUP BY User HAVING COUNT(*)=2


Правда план выполнения запроса в этом случае хреновый
Quote:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE test ALL test_Type_Index,test_Value_Index 11 Using where; Using temporary; Using filesort

Using temporary; Using filesort - это то, из-за чего в первую очередь тормозят запросы.


Для первого запроса:
Code:
explain select * from test AS t1
INNER JOIN test AS t2 ON t2.User = t1.User
where t1.User = 'Ivanov' and (t1.Type = 'School' and t1.Value = '11') and (t2.Type = 'Institute' and t2.Value = 'MGU');


Quote:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref test_User_Index,test_Type_Index,test_Value_Index test_User_Index 22 const 2 Using where

1 SIMPLE t2 ref test_User_Index,test_Type_Index,test_Value_Index test_User_Index 22 const 2 Using where


Для второго:
Code:
explain select * from test as t1
where type = 'School' and value = '11'
   and exists ( select * from test as t2
                     where user = t1.user and type = 'Institute' and value = 'MGU' )

Quote:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ref test_Type_Index,test_Value_Index test_Value_Index 33 const 3 Using where

2 DEPENDENT SUBQUERY t2 ref test_User_Index,test_Type_Index,test_Value_Index test_User_Index 22 wwwsapnetru.t1.User 2 Using where

_________________
Молитва - это запрос разработчику на изменение кода программы.
Back to top
View user's profile Send private message Blog Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Talks | Беседка All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG.
SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG.
Every effort is made to ensure content integrity. Use information on this site at your own risk.