2014-02-20 2 views
1

Предположим, что у меня есть эти таблицы:SQL Заказывая сложный запрос

items, в котором хранятся предметы.

CREATE TABLE items 
(
    id serial NOT NULL, 
    name character varying(255), 
    rarity character varying(255), 
    created_at timestamp without time zone, 
    updated_at timestamp without time zone, 
    CONSTRAINT items_pkey PRIMARY KEY (id) 
) 

item_modifiers, который управляет многие-ко-многим между элементами и модификаторов

CREATE TABLE item_modifiers 
(
    id serial NOT NULL, 
    item_id integer, 
    modifier_id integer, 
    primary_value integer, 
    secondary_value integer, 
    CONSTRAINT item_modifiers_pkey PRIMARY KEY (id) 
) 

modifiers, который содержит все возможные модификаторы Пункт

CREATE TABLE modifiers 
(
    id serial NOT NULL, 
    name character varying(255), 
    CONSTRAINT explicit_mods_pkey PRIMARY KEY (id) 
) 

Теперь предположим, что у меня есть комплекс запрос. Я хочу, чтобы найти все элементы, которые имеют модификаторы с ID 1 и 2, упорядоченные по PRIMARY_VALUE модификатора с идентификатором 1.

Я попробовал этот запрос

SELECT "items".*, item_modifiers.primary_value FROM "items" 
INNER JOIN item_modifiers ON item_modifiers.item_id = items.id 
AND ((item_modifiers.modifier_id = 1) 
OR (item_modifiers.modifier_id = 2)) 
GROUP BY items.id, item_modifiers.primary_value 
HAVING 
COUNT(item_modifiers.id) = 2 
ORDER BY item_modifiers.primary_value DESC 

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

EDIT я построил SQL скрипку, чтобы продемонстрировать http://sqlfiddle.com/#!15/30887/1

ответ

1

Вы не должны вступать с item_modifiers с modifier_id 2, вы только этого гарантировали, что такие записи EXESTS:

SELECT items.*, item_modifiers.primary_value 
FROM items 
INNER JOIN item_modifiers ON item_modifiers.item_id = items.id AND item_modifiers.modifier_id = 1 
WHERE EXISTS 
(
    SELECT * 
    FROM item_modifiers 
    WHERE item_modifiers.item_id = items.id AND item_modifiers.modifier_id = 2 
) 
ORDER BY item_modifiers.primary_value DESC; 

Ее e - ваш скрипт SQL: http://sqlfiddle.com/#!15/30887/9

+1

Вот еще один способ решить это, лишь слегка изменив ваше утверждение: http://sqlfiddle.com/#!15/30887/17. –

+0

Это почти это, за исключением теперь (на моем производстве db) некоторые primary_values ​​пусты, и они появляются вверху. Есть ли способ, чтобы пустые значения отображались внизу, используя часть CASE THEN WHEN в вашем втором sqlfiddle? –

+1

Поскольку primary_value является целым числом, пустое значение означает NULL. Вы можете использовать ORDER BY .... DESC NULLS LAST, чтобы переместить их в конец списка результатов. –

0

ли это то, что вы ищете:

SELECT "items".*, 
     item_modifiers.primary_value 
FROM "items" 
     INNER JOIN item_modifiers 
       ON item_modifiers.item_id = items.id 
        AND ((item_modifiers.modifier_id = 1) 
         OR (item_modifiers.modifier_id = 2)) 
ORDER BY item_modifiers.primary_value DESC;