2016-07-12 2 views
-1

Мне нужно найти способ «конкатенировать» два поля (что-то вроде key => value). Например, в этом запросе я хочу показывать только те объекты, где (fielddef_id = 4 => fieldval.value = "Documents téléchargeables") AND (fielddef_id = 5 => fieldval.value = "Anglais").Сложный запрос mySQL с совместными и настраиваемыми полями

Таблица fielddef сохраняет ключевые Таблица fieldvalue сохраняет значение

Но есть много комбинаций: ключ = значение ... (например: LANG = английский, тип = downolad)

SELECT item.item_id AS id, item.title AS title, item.active AS active, item_cat.category_id AS cat_id, item_cat.item_id AS item_id, category.category_id, category.category_name as cat_name, category.category_alias as cat_alias 
FROM `cms_module_listit2ressources_item` AS item 
LEFT JOIN `cms_module_listit2ressources_item_categories` AS item_cat 
ON item.item_id = item_cat.item_id 
LEFT JOIN `cms_module_listit2ressources_category` AS category 
ON item_cat.category_id = category.category_id 
LEFT JOIN `cms_module_listit2ressources_fieldval` AS fieldval 
ON item.item_id = fieldval.item_id 
LEFT JOIN `cms_module_listit2ressources_fielddef` AS fielddef 
ON fieldval.fielddef_id = fielddef.fielddef_id 
WHERE item.active=1 
AND (fielddef.fielddef_id="4" AND fieldval.value IN ("Documents téléchargeables")) 
AND (fielddef.fielddef_id="5" AND fieldval.value IN ("Anglais")) 

Это упрощенный пример, который позволит вам узнать, что я хочу сделать ... Обратите внимание, что я не могу изменить концепцию базы данных.

TABLE ITEMS Store the ID and Title of an item. 
id= INT/Primary/auto_increment 
title = VARCHAR (255) 

Каждый товар имеет множество настраиваемых полей (например: "цвет = красный", "Страна = Франция", и т.д ..)

TABLE CUSTOM_FIELDNAME Stores the fieldname (definition => example : "Color", "Country") 
fielddef_id = INT/PRIMARY/auto_increment 
name = VARCHAR(255) (=> ex: Color, Country...) 

TABLE CUSTOM_FIELDVALUE stores the field value (example : "red", "France") 
item_id => foreign_key to link to the ITEMS TABLE 
fielddef_id => foreign_key to link to the CUSTOM_FIELDNAME TABLE 
value = VARCHAR(255) (=> ex: red, France...) 

мне нужно перечислить только те элементы, где цвет = красный и Country = ФРАНЦИЯ

Примеры Данные:

TABLE ITEMS : 
id=1 | Title = "first Item" 
id=2 | Title = "A red French Item" 

TABLE CUSTOM_FIELDNAME 
fielddef_id = 1 | name = "Color" 
fielddef_id = 2 | name = "Country" 

TABLE CUSTOM_FIELDVALUE 
item_id = 1 | fielddef_id = 1 | value = "Blue" 
item_id = 1 | fielddef_id = 2 | value = "Germany" 
item_id = 2 | fielddef_id = 1 | value = "Red" 
item_id = 2 | fielddef_id = 2 | value = "France" 

Так что мой запрос выглядит следующим образом:

SELECT items.title AS title 
custom_fieldname.name as customName 
custom_fieldvalue.value as customValue 
FROM `items` 
LEFT JOIN `custom_fieldvalue` 
ON items.id = custom_fieldvalue.item_id 
LEFT JOIN `custom_fieldname` 
ON custom_fieldvalue.fielddef_id = custom_fieldname.fielddef_id 
WHERE(custom_fieldname.fielddef_id="1" AND custom_fieldvalue.value "Red") AND (custom_fieldname.fielddef_id="2" AND custom_fieldvalue.value "France") 
+0

Pls обеспечить некоторый образец данных и ожидаемого результата на основе выборочных данных. В настоящее время ваш вопрос мне непонятен. Если бы я должен был догадаться, вы ищете group_concat(). – Shadow

+0

Принимая во внимание точку Саги о помещении условий LEFT JOIN в предложение ON, одним из вариантов является LEFT JOIN таблицы fielddef и fiedval дважды, один раз для каждого условия. Другой вариант, который медленнее, но легче читать, - это классический синтаксис «MAX (CASE WHEN ...)» типичного сводного запроса. – Strawberry

ответ

0

Например:

SELECT i.item_id AS id 
    , item.title AS title 
    , item.active AS active 
    , item_cat.category_id AS cat_id 
    , item_cat.item_id AS item_id 
    , category.category_id 
    , category.category_name as cat_name 
    , category.category_alias as cat_alias 
    , v4.value v4_value 
    , d4.fielddef_id d4_fielddef_id 
    , v5.value v5_value 
    , d5.fielddef_id d5_fielddef_id 
    FROM cms_module_listit2ressources_item i 
    LEFT 
    JOIN cms_module_listit2ressources_item_categories ic 
    ON ic.item_id = i.item_id 
    LEFT 
    JOIN cms_module_listit2ressources_category c 
    ON c.category_id = ic.category_id 
    LEFT 
    JOIN cms_module_listit2ressources_fieldval v4 
    ON v4.item_id = i.item_id 
    AND v4.value IN ("Documents téléchargeables") 
    LEFT 
    JOIN cms_module_listit2ressources_fielddef d4 
    ON d4.fielddef_id = v4.fielddef_id 
    AND d4.fielddef_id = 4 
    LEFT 
    JOIN cms_module_listit2ressources_fieldval v5 
    ON v5.item_id = i.item_id 
    AND v5.value IN ("Anglais") 
    LEFT 
    JOIN cms_module_listit2ressources_fielddef d5 
    ON d5.fielddef_id = v5.fielddef_id 
    AND d5.fielddef_id = 5 
WHERE i.active = 1; 
+0

Спасибо, это работает! Я только заменил LEFT JOIN INNER JOIN, чтобы соответствовать только тогда, когда оба условия завершены! –

1

Во-первых, НЕ ОН поставил условия в правой таблице LEFT JOIN в предложении WHERE, их следует размещать только в предложении ON().

Во-вторых, ваше последнее условие не имеет смысла и всегда будет FALSE, поле не может быть равно более 1 значения за раз.

В-третьих, сравнение строк должно выполняться с помощью одной цитаты ', а не двойной ".

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

SELECT CONCAT(First_Field,'=>',Second_Field) 
FROM `cms_module_listit2ressources_item` AS item 
LEFT JOIN `cms_module_listit2ressources_item_categories` AS item_cat 
ON item.item_id = item_cat.item_id 
LEFT JOIN `cms_module_listit2ressources_category` AS category 
ON item_cat.category_id = category.category_id 
LEFT JOIN `cms_module_listit2ressources_fieldval` AS fieldval 
ON item.item_id = fieldval.item_id 
LEFT JOIN `cms_module_listit2ressources_fielddef` AS fielddef 
ON fieldval.fielddef_id = fielddef.fielddef_id  AND 
    (fielddef.fielddef_id,fieldval.value) IN(('4','Documents téléchargeables), 
              ('5','Anglais')) 
WHERE item.active=1 
+0

Вы никогда не должны использовать CONCAT. Ни для чего. Когда-либо. – Strawberry

+0

Обычно, когда вы говорите что-то вроде этого, вы должны объяснить, почему. – sagi

+0

Поскольку CONCAT и GROUP_CONCAT подрывают атомарность данных SQL. Существует (почти) ничего, что вы можете сделать с теми функциями, которые не могут быть более эффективными в коде уровня приложения. – Strawberry