Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS SQL Server > Можноли оптимизировать


Автор: Artemon 9.2.2006, 20:22
Можноли в данной ф-ии оптимизировать SQL запросы
Код

  bool WORK_WITH_BASE::Get_GenresCount
                                      (
                                      long int& Count,                                                   
                                      AnsiString GenreName
                                      )
{
  Count = 0;
  AnsiString Str = "";
  long int ID_ARTIST;

  Str = "SELECT ID_GENRE FROM GENRES "
        "WHERE GENRE = '" + GenreName + "' "
        ;

  if( ExecuteAnySQL(Str, QueryGenres ) != ERROR_ALL_OK) return FALSE;  
  if( !QueryGenres->RecordCount ) return;
  
  QueryGenres->First();
  ID_ARTIST = QueryGenres->FieldByName("ID_ALBUM")->Value;

  while( !QueryGenres->Eof )
       {
       Str = "SELECT ARTIST FROM ARTISTS "
             "WHERE ID_ARTIST = " + IntToStr(ID_ARTIST) + " "
             ;

       if( ExecuteAnySQL(Str, QueryArtists ) != ERROR_ALL_OK) return FALSE;  
       Count += QueryArtists->RecordCount;

       QueryGenres->Next();
       }

  return true;
}

Автор: Artemon 9.2.2006, 20:45
Не тот код привел вот то, что хотел показать
Код

  bool WORK_WITH_BASE::Get_GenresCount
                                      (
                                      long int& Count,        // Ñþäà áóäåò çàïèñàíî ÷èñëî àðòèñòîâ
                                      AnsiString GenreName    // Æàíð
                                      )
{
  Count = 0;
  AnsiString Str = "";
  long int ID_GENRE = 0 ;

  Str = "SELECT ID_GENRE FROM GENRES "
        "WHERE GENRE = '" + GenreName + "' "
        ;

  if( ExecuteAnySQL(Str, QueryGenres ) != ERROR_ALL_OK) return FALSE;  // Îøèáêà ïðè âûïîëíåíèè SQL çàïðîñà

  if( !QueryGenres->RecordCount ) return true;

  QueryGenres->First();
  ID_GENRE = QueryGenres->FieldByName("ID_GENRE")->Value;

  while( !QueryGenres->Eof )
       {
       Str = "SELECT ARTIST FROM ARTISTS "
             "WHERE ID_GENRE = " + IntToStr(ID_GENRE) + " "
             ;

       if( ExecuteAnySQL(Str, QueryArtists ) != ERROR_ALL_OK) return FALSE;  // Îøèáêà ïðè âûïîëíåíèè SQL çàïðîñà

       Count += QueryArtists->RecordCount;

       QueryGenres->Next();
       }

  return true;
}

Добавлено @ 20:59
Другими словами - имеется две таблицы:

1)
GENRES

ID_GENRE - numeric
GENRE - str

2)
ARTISTS

ID_ARTISTS - numeric
ARTIST - str


Вопрос:

Как из ARTISTS выбрать все записи зная только GENRE.

P.S.
Способ который я привел - работает - но он бесспорно УРОДЛИВ.
Мне почему-то кажется, что данную задачу - можно решить одним запросом...............


Автор: boevik 9.2.2006, 22:07
Можно использовать subquery или join.
Код

SELECT ARTIST 
FROM ARTISTS 
WHERE ID_GENRE in (SELECT ID_GENRE 
                                   FROM GENRES
                                   WHERE GENRE = 'some name'

Но лучше join
Код

SELECT ARTIST 
FROM ARTISTS 
   INNER JOIN GENRES
      ON ARTISTS.ID_GENRE = GENRES.ID_GENRE 
WHERE GENRE = 'some name'


Автор: Artemon 10.2.2006, 14:58
Спасибо Boevik, все работает.

Еще один вопрос на этуже т ему.

Имеются две таблицы:

1)
GENRES

ID_GENRE - numeric
GENRE - str


2)
ARTISTS

ID_ARTIST - numeric
ARTIST - str


Как выполнить следующую задачу:

1) В таблице GENRES по полю GENRE найти записи по заданному тексту например "РОК" и удалить их все кроме первой.
2) В таблице ARTISTS изменить ID_GENRE удаленных записей (1) на ID_GENRE оставшейся записи.

Я это реализовал, но как мне кажется опять криво.

Помогите пожалуйста.


bool WORK_WITH_BASE::ChangeGenre
(
AnsiString From,
AnsiString To
)
{
AnsiString Str = "";
long int ID_GENRE, tmp;

Str = "UPDATE GENRES SET GENRE = '" + To + "' "
"WHERE GENRE = '" + From + "' "
;

if( ExecuteAnySQL(Str, QueryGenres) != ERROR_ALL_OK) return FALSE;

Str = "SELECT ID_GENRE FROM GENRES "
"WHERE GENRE = '" + To + "' "
;

if( ExecuteAnySQL(Str, QueryGenres) != ERROR_ALL_OK) return FALSE;

if( QueryGenres->RecordCount )
{
QueryGenres->First();
ID_GENRE = QueryGenres->FieldByName("ID_GENRE")->Value;
}

while( QueryGenres->RecordCount > 1 )
{
QueryGenres->Last();

tmp = QueryGenres->FieldByName("ID_GENRE")->Value;

Str = "UPDATE ARTISTS SET ID_GENRE = " + IntToStr(ID_GENRE) + " "
"WHERE ID_GENRE = " + IntToStr(tmp) + " "
;

if( ExecuteAnySQL(Str, QueryArtists) != ERROR_ALL_OK) return FALSE;

QueryGenres->Delete();
}

return true;
}


Автор: boevik 10.2.2006, 15:32
Примерно так.
Начнем со втoрой задачи

Код

update ARTISTS 
set ID_GENRE = (select min(ID_GENRE) from GENRES where GENRE = 'ROK')
from ARTISTS inner join GENRES 
on ARTISTS.ID_GENRE = GENRES.ID_GENRE
where GENRE = 'ROK'

После этого можно удалять записи из GENRES
Код

delete from GENRES 
where ID_GENRE > (select min(ID_GENRE) from GENRES where GENRE = 'ROK')
and GENRE = 'ROK'

Автор: Artemon 10.2.2006, 16:08
Boevik - ты мне очень помог, мне даже вголову не приходило так организовать запросы.

Еще один вопрос типа предыдущих двух появился, сейчас я свое решение напишу, а если оно опять будет уродское я его покажу.

Автор: Artemon 10.2.2006, 18:50
Имеются 3 таблицы:


1) ARTISTS

ID_ARTISTS - numeric
ID_GENRE - numeric
ARTIST - str

2) ALBUMS

ID_ALBUM - numeric
ID_ARTIST - numeric
ALBUM - str
................
.................

3) SONGS

ID_SONG - numeric
ID_ALBUM - numeric
SONG - str

Задача - Удалить Артиста его альбомы и композиции.

Помогите сделать все проще.

Мое решение опять кривое, но работает:

bool WORK_WITH_BASE::DeleteArtist( AnsiString ArtName )
{
long int ID_ARTIST, ID_ALBUM;
AnsiString Str = "";

Str = "SELECT ID_ARTIST FROM ARTISTS "
"WHERE ARTIST = '" + ArtName + "' "
;

if( ExecuteAnySQL(Str, QueryArtists) != ERROR_ALL_OK) return FALSE;

while( QueryArtists->RecordCount )
{
QueryArtists->First();
ID_ARTIST = QueryArtists->FieldByName("ID_ARTIST")->Value;

Str = "SELECT ID_ALBUM FROM ALBUMS "
"WHERE ID_ARTIST = '" + IntToStr(ID_ARTIST) + "' "
;

if( ExecuteAnySQL(Str, QueryAlbums) != ERROR_ALL_OK) return FALSE;
while( QueryAlbums->RecordCount )
{
QueryAlbums->First();
ID_ALBUM = QueryAlbums->FieldByName("ID_ALBUM")->Value;

Str = "SELECT ID_SONG FROM SONGS "
"WHERE ID_ALBUM = '" + IntToStr(ID_ALBUM) + "' "
;

if( ExecuteAnySQL(Str, QuerySongs) != ERROR_ALL_OK) return FALSE; while( QuerySongs->RecordCount )
{
QuerySongs->First();
QuerySongs->Delete(); // Delete Song
}
QueryAlbums->Delete(); // Delete Album
}
QueryArtists->Delete(); // Delete Artist
}

return true;
}

Автор: boevik 10.2.2006, 22:58
По той же схеме как и раньше.
Код

delete SONGS 
from ARTISTS inner join ALBUMS
on ARTISTS.ID_ID_ARTISTS = ALBUMS.ID_ARTIST 
inner join SONGS 
on ALBUMS.ID_ALBUM = SONGS.ID_ALBUM 
WHERE ARTIST = 'artist_name'

Код

delete ALBUMS 
from ARTISTS inner join ALBUMS
on ARTISTS.ID_ID_ARTISTS = ALBUMS.ID_ARTIST 
WHERE ARTIST = 'artist_name'

Код

delete  
from ARTISTS 
WHERE ARTIST = 'artist_name'

Естественно, не нужно ни каких циклов и т.п.. Все выполняется в 3 вызова.

Автор: Artemon 11.2.2006, 08:39
Супер!!!!

Спасибо

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)