[MySQL-гуру] Сложный запрос к базе

Тема в разделе "Базы данных", создана пользователем DOLARiON, 20 ноя 2008.

Статус темы:
Закрыта.
Модераторы: latteo
  1. DOLARiON

    DOLARiON

    Регистр.:
    4 сен 2006
    Сообщения:
    191
    Симпатии:
    48
    итак есть огромная база с примерно такими таблицами:

    Table `Group` {
    id,
    user,
    param1_i,
    param1,
    param2_i,
    param2,
    ...
    param9_i,
    param9
    } - все поля числовые
    ~порядка 50 000 000 записей

    соответственно каждое поле в таблице соответствует ID в другой таблице, где и лежат уже все необходимые данные

    т.е.:

    Table `Group` {
    id, --> порядковый номер записи (набор параметров)
    user, --> ID юзера -> таблица users

    ~
    до этого момента все просто
    LEFT JOIN `users` и полетели

    ...а вот дальше как быть:
    ~

    param1_i, --> ID базы с данными... к примеру если param1_i == 1, то база с параметрами param_aa, если param1_i == 2, то база с параметрами param_ab... и т.д.
    param1, --> соответственно, если param1_i == 1, то делаем лефт джоин таблички param_aa
    param2_i, --> следующий параметр базы (к примеру == 10)
    param2, --> соответственно выбираем из базы param_XX (последние 2 бкуы базы на основе param2_i), где param_XX.ID == param2
    ...
    ну и т.д.

    соответственно, за один присест (запрос) может быть до 10 инклюдов базы
    }

    соответственно, у меня есть изначальная разлиновка... какой параметр таблицы (paramX_i) соответствует какая таблица param_XX - тут все банально:
    id - table
    1 - aa
    2 - ab
    3 - ac
    4 - ad
    ...
    и т.д.
    до zz
    итого 676...

    уважаемые Знатоки, а теперь внимание вопрос :)

    как динамично подставлять таблицу?!
    т.е.
    у меня запрос
    SELECT *
    from `Group`
    where `user`
    LIMIT 10

    соответственно сюда добавляем ЛЕФТ ДЖОИН users -> получаем инфу о юзере,

    нужно так же подставлять
    базу под каждый param и получать из нее данные одним запросом

    PS. я вот тут подумал... может процедурами сделать?! ......правда ни разу их не юзал :nezn:
     
  2. Pedr0

    Pedr0 Создатель

    Регистр.:
    28 авг 2008
    Сообщения:
    17
    Симпатии:
    0
    Сначала из-за наличия путанных выражений с участием слов "база", "таблица" ничерта не понял, разобрался что ты приблизительно хочешь только после боевых "стограммов" и повторного прочтения.
    сначала думал поможет банальный IF-ELSE? поняв масштаб задумманого остается только вариант с динамическим SQL, собирается строка с SQL-запросом и запускается оператором EXECUTE. Читай хелп, сам юзал один единственный раз и то случайно :) потом ушел от него переделав конструкцию работы приложения.
    вот и примерчик

    -- Execute the SELECT statement.
    declare @test varchar(30)
    set @test = 'select * from test'
    execute(@test)

    еще пример
    SET @s = CONCAT('SELECT * FROM authors WHERE id BETWEEN ', _min, ' AND ', _max);
    PREPARE stmt1 FROM @s;
    EXECUTE stmt1;

    и еще пример

    SET @s = 'SELECT * FROM authors WHERE id BETWEEN ? AND ?';
    SET @min = _min;
    SET @max = _max;

    PREPARE stmt1 FROM @s;
    EXECUTE stmt1 USING @min, @max;
    DEALLOCATE PREPARE stmt1;

    надеюсь поможет.
     
  3. elcaste

    elcaste

    Регистр.:
    30 ноя 2007
    Сообщения:
    322
    Симпатии:
    175
    Какая то каша сплошная, определись, где у тебя база, а где таблица, и какой вывод хочешь получить в итоге. :)
     
  4. DOLARiON

    DOLARiON

    Регистр.:
    4 сен 2006
    Сообщения:
    191
    Симпатии:
    48
    ё!
    короче,
    есть таблицы:

    Table `Group` {
    id,
    user,
    param1_i,
    param1,
    param2_i,
    param2,
    ...
    param9_i,
    param9

    }

    Table `user` {
    id,
    name

    }

    Table `param_aa` {
    id,
    name

    }

    Table `param_ab` {
    id,
    name

    }

    Table `param_ac` {
    id,
    name

    }
    и т.д.
    до
    Table `param_zz` {
    id,
    name

    }

    нужно сделать запрос выборки

    SELECT *
    FROM `Group`
    Where бла-бла-бла


    таким образом что

    у нас есть два поля
    param1_i - идентификатор таблицы из которой нужно брять значение
    param1 - id записи из этой самой таблицы

    соответственно чтобы вместо поля
    param1
    подставилось значение из таблицы param_XX с ID == param1,

    таблица соответствия
    param1_i с названием таблицы выглядит след. образом:

    param1_i | table
    1 aa
    2 ab
    ...
    676 zz

    к примеру

    если param1_i == 2, param1 == 200, то нам надо
    LEFT JOIN `param_ab` где param_ab.id = 200

    ну и сопоставить
    param1 = param_ab.name

    проблема в том что:
    в базе хранятся записи в абсолютно разрозненном состоянии, т.е. может быть:

    param1_i == 2
    param1 == 200

    param2_i == 3
    param2 == 201

    param3_i == 1
    param3 == 202

    тогда нам надо сделать
    LEFT JOIN `param_ab` где param_ab.id = param1 (т.е. = 200)
    LEFT JOIN `param_ac` где param_ac.id = param2 (т.е. = 201)
    LEFT JOIN `param_aa` где param_aa.id = param3 (т.е. = 202)


    вопрос в динамичном подставлении инклюда в процессе выборки

    т.е. когда мы выдергиваем 200 записей из таблицы `Group` нужно чтобы КАЖДАЯ выдернтая запись получила свои данные из своей таблицы с param_XX

    теперь понятно? :)

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

    На самом деле
    стоит каешна эту таблицу переконвертнуть, но вот вопрос...

    какая структура базы выдержит 50КК записей при условии, что данные выглядят след образом:

    id - цифра
    user - имя + ID в системе - тут понятно

    param1 - varchar 255
    param2 - varchar 255
    ...
    param9 - varchar 255

    причем список этих самых описаний `param` (окурат размещаемых в базах с `param_aa` по `param_zz`) - един... всего ~ 2kk слов и выражений, т.е. можно каешна хранить их в одной большой таблице и делать инклюд ее....но... я себе не представляю поиск по 2кк записям..... или я не прав?!
     
  5. elcaste

    elcaste

    Регистр.:
    30 ноя 2007
    Сообщения:
    322
    Симпатии:
    175
    Теперь ясно.
    Функции тут могут помочь только отчасти - для определения имени таблицы по ее идентификатору:

    CREATE FUNCTION `GETNAME`(tabid INT)
    RETURNS varchar(10) CHARSET latin1
    BEGIN
    DECLARE o1 varchar(10);
    SELECT tabname INTO o1 FROM `links` WHERE `idt`=tabid;
    RETURN o1;
    END;

    потому что имена таблиц и полей нельзя передать в качестве параметров в функцию. Это можно сделать в процедурах, НО процедуры не возвращают значения(точнее возвращают, но в нашем контексте это будет через жопу - можно сделать с выводом во временную таблицу).
    ИМХО, намного быстрее в плане реализации будет написать на другом языке с использованием простых SQL запросов.

    PS: Как вариант, можно создать функцию(получится размером где-то в 700 строк), которая учитывала бы все имена таблиц по их идентификатору, но это уже зависит от того, насколько динамична таблица соответствий.
     
  6. SEOKinG

    SEOKinG

    Регистр.:
    2 дек 2008
    Сообщения:
    346
    Симпатии:
    69
    так как я не могу создать отдельный топик.

    имеется база данных Mysql, в этой базе данных установлен WP.
    теперь мне надо выполнить нужный запрос для этой Mysql базы.
    проблема в чём. вкладку "выполнить запрос" в панеле PhpMyadmin я вижу. а дальше тупик.

    p.s. сам запрос конечно имеется
     
  7. Counters

    Counters Постоялец

    Регистр.:
    7 сен 2006
    Сообщения:
    82
    Симпатии:
    11
    Если хотите я сделаю всё одним маленьким SQL запросом, только в данном топике всё запутано, так что либо в ПМ по 3 строки обоих таблиц либо, выкладывайте сюда.
     
  8. AndreyD2

    AndreyD2

    Регистр.:
    21 окт 2008
    Сообщения:
    195
    Симпатии:
    67
    Решения зависит от нескольких параметров.
    1. Запрос идет из программы: sql-запрос можно составить в тексте программы.
    (на времени выполнения не скажется).
    2. Запрос жестко забит на сервере SQL - тогда единственный выход написание динамических запросов в процедуре.
    3. Частный случай как у тебя - когда в param-таблицах одно поле name:
    Select *, dbo.[func_value](param_I,param) as [Твое значение] from group
    Далее можешь джонить все что хочешь user,...
    Структура таблицы group следующая:
    [Group]
    ID Int
    user Int
    param_I int - псевдоним таблицы (1 - param1, 2 - param3,...)
    param int - ключ записи в таблице
    Текст функции:
    Код:
    SET QUOTED_IDENTIFIER ON 
    GO
    SET ANSI_NULLS ON 
    GO
    CREATE     FUNCTION [dbo].[func_value] (@param Int,@id int)
    RETURNS money
    AS
    BEGIN
      Declare @str varchar(255)
      Set @str = 
    	case @param
    	when 1 then (select name from param1)
    	when 2 then (select name from param3)
    	when 3 then (select name from param2) 
    	when 4 then (select name from param5)
    	when 5 then (select name from param7)
    	when 6 then (select name from param4)
    RETURN @str
    END
    GO
    SET QUOTED_IDENTIFIER OFF 
    GO
    SET ANSI_NULLS ON 
    GO
    
     
Статус темы:
Закрыта.