За последние 24 часа нас посетили 22500 программистов и 1110 роботов. Сейчас ищут 620 программистов ...

Выборка из таблицы с замещением ( JOIN ?)

Тема в разделе "MySQL", создана пользователем AterCattus, 5 сен 2008.

  1. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Никак не могу разобраться с запросом. Можно сделать простой запрос и немного потом по результатам прошерстить php, но ищу решение только средствами sql.

    Есть две таблицы, скажем A и B:
    Код (Text):
    1. A ( ключ и значение )
    2. id | value
    3. 1  | foo
    4. 2  | bar
    5.  
    6. B ( ключ, внешний ключ на A.id, внешний ключ на пользователя, значение )
    7. id | a_id | user_id | value
    8. 1  | 1    | 0       | foofoo
    9. 2  | 2    | 7       | barbar
    10. 3  | 1    | 1       | foobar
    11. 4  | 2    | 1       | barboo
    Если user_id равно 0, то это считается "значением по умолчанию". Т.е. если для определенного пользователя нет соответствующей строки с a_id, то берется строка ( a_id=требуемое_a_id, user_id=0 ).
    Строки "по умолчанию" есть для всех возможных значений a_id.

    Стоит проблема запроса для выборки всех записей по данному пользователю.
    Вот к примеру результат выборки по пользователям 1 и 7:
    Код (Text):
    1. Результат:
    2. id | user_id | a_value | value
    3. 3  | 1       | foo     | foobar
    4. 4  | 1       | bar     | barfoo
    5. 1  | 7       | foo     | foofoo ; подставлено значение по умолчанию ( user_id=0 )
    6. 2  | 7       | bar     | barbar
    Третья строка содержит значение по умолчанию, т.к. нет соответствующего значения.

    В принципе это запрос вида "Выбрать все записи по user_id равному заданному плюс те записи из этой же таблицы, в которых a_id еще не выбран, а user_id=0".

    Никак не могу составить нужный запрос. Ищу помощи...
     
  2. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    AterCattus
    Возможно, получится подзапросом, который выбирает данные по одному user_id, причем в условие поставить 'user_id IN ($user_id,0)', а сортировать по 'user_id DESC' и добавить LIMIT 1, тогда будет выбираться либо нужна запись, либо соответствующая user_id=0, если нужной нет... но с точки зрения оптимизации запрос будет выглядеть страшновато, может, все-таки обработать в PHP более простой и быстрый запрос?
     
  3. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Вот и я сижу над этим запросом в попытках оптимизации.
    Просто отдавать PHP все записи, а потом в них уже искать неуказанные и для них искать значения "по умолчанию"... Тут и объем данных от SQL сервера больше и много времени это дело крутить уже в PHP.
     
  4. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    AterCattus
    А если так?
    [sql]SELECT A.value AS avalue, B.* FROM A,B WHERE A.id=B.a_id AND (user_id=$user_id OR
    (user_id=0 AND a_id NOT IN
    (SELECT DISTINCT(a_id) FROM B WHERE user_id=$user_id)))[/sql]
     
  5. DarkElf

    DarkElf Активный пользователь

    С нами с:
    22 окт 2006
    Сообщения:
    1.632
    Симпатии:
    0
    Dagdamor

    [sql]SELECT IFNULL(`a`.`value`,'значение по-умолчанию') FROM `b` LEFT JOIN `a` ON `a`.`a_id` = `b`.`id` AND `b`.`user_id` IN (1,7)[/sql]

    может так?
     
  6. Dagdamor

    Dagdamor Активный пользователь

    С нами с:
    4 фев 2006
    Сообщения:
    2.095
    Симпатии:
    1
    Адрес:
    Барнаул
    DarkElf
    Проблема в том, что значение по умолчанию заранее неизвестно, оно тоже где-то там в таблице :)
     
  7. DarkElf

    DarkElf Активный пользователь

    С нами с:
    22 окт 2006
    Сообщения:
    1.632
    Симпатии:
    0
    Dagdamor
    ну, ток вместо 'значение по-умолчанию' подставить имя поля, в котором это значение содержится:)
     
  8. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Все, я тогда разобрался с этим запросом. Получилось довольно таки коротко. Спасибо.

    Вот только сейчас возник вопрос подобного плана. Решил опубликовать его здесь же.

    Есть таблица catalog_product (cp), в ней содержится некоторая общая информация о продуктах. Из важного для вопроса стоит указать только ключ id. И есть две таблицы catalog_property_name и catalog_property_value, в паре описывающие дополнительные свойства для продуктов. Первая таблица содержит названия свойств ( id, name ), а вторая соответственно значения этих свойств для каждого товара ( id, id_property_name, id_product, value ).

    Взаимосвязь осуществляется следующим образом:
    [sql]catalog_property_value.id_property_name = catalog_property_name.id
    catalog_property_value.id_product = catalog_product.id[/sql]

    И из всего этого нужно сделать выборку продуктов с выдачей сразу и всех свойств данного продукта в качестве дополнительных колонок ответа.
    Примерно так:
    Код (Text):
    1. id-товара ; id-первого свойства ; id-второго свойства ; ...
    2. 23 ; значение первого свойства ; значение второго свойства ; ...
    Одно поле я выбрать смог, но вот как выбрать все поля свойств?

    Важно! Количество свойств не известно. Иначе бы я просто перечислил их в SELECT.