Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Базы данных: SQL > Необходима помощь с составлением SQL-запроса


Автор: Костик+ 12.07.23, 13:32
Доброго времени суток, всем!
Собственно, сабж.

Есть таблица вида:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ProductId   |AttrId        |AttrValueId  
    ------------+--------------+-----------------
    1           |5             |1010
    1           |7             |954
    1           |8             |352
    1           |9             |21057
    1           |14            |221
    2           |4             |997
    2           |5             |2350
    2           |8             |352
    2           |9             |20533
    2           |14            |232
    3           |5             |1010
    3           |8             |352
    3           |9             |27044
    4           |5             |1010
    4           |7             |964
    4           |8             |331
    4           |14            |219
    //...


Каждый ProductId может иметь только один уникальный AttrId.
Необходимо выбрать из таблицы все ProductId, удовлетворяющие условию, когда определённые атрибуты содержат соответствующие Value. Например,
выбрать товары, в для которых AttrId 5 содержит Value 1010 и AttrId 8 содержит Value 352:
5 => 1010 и 8 => 352

Т.е., получается что-то типа такого:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    SELECT
      ProductID
    FROM
      ProductTable
    WHERE
      (AttrId = 5 AND AttrValueId = 1010)
      AND
      (AttrId = 8 AND AttrValueId = 352)


В результате выполнения подобного запроса для таблицы из примера выше, получим выборку:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ProductId
    ----------
    1
    3


ProductId 2 и 4 не подойдут, т.к. для них выполняется только одно из условий.

БД: MSSQL.

Надеюсь, правильно сформулировал свою мысль.

Автор: Majestio 12.07.23, 13:51
Цитата Костик+ @
Каждый ProductId может иметь только один AttrId.

В таблице ProductId = 1 имеет пять AttrId ... дальше не читал :)

Автор: Akina 12.07.23, 16:20
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    SELECT ProductID
    FROM ProductTable
    WHERE ( AttrId, AttrValueId ) IN ( (5, 1010), (8, 352) )
    GROUP BY ProductID
    HAVING COUNT( /* DISTINCT */ AttrId ) = 2

Автор: Костик+ 12.07.23, 16:23
Цитата Majestio @
В таблице ProductId = 1 имеет пять AttrId ... дальше не читал

Да, спасибо. Резонное замечание. Прошу прощения, с утра не выспался. Имеется ввиду, что параметр AttrId уникален для каждого ProductId. Т.е. ситуация:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ProductId | AttrId
    ----------+--------
    1         |5
    1         |6
    1         |7
    //...

может быть, а:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    ProductId | AttrId
    ----------+--------
    1         |4
    1         |4
    1         |4

не может.

Автор: Majestio 12.07.23, 17:17
Цитата Костик+ @
Т.е., получается что-то типа такого:

В операторе WHERE собирай условия не по "и", а по "или", и всё получится:

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    SELECT
      ProductID
    FROM
      ProductTable
    WHERE
      (AttrId = 5 AND AttrValueId = 1010)
      OR -- <--- тут
      (AttrId = 8 AND AttrValueId = 352)

Автор: Akina 12.07.23, 17:46
Цитата Majestio @
В операторе WHERE собирай условия не по "и", а по "или", и всё получится

Не, фигня получится - на показанных данных такой запрос вернёт ещё и ProductID=4, у которого AttrId = 8 имеет значение AttrValueId = 331.

Автор: Majestio 12.07.23, 19:57
Цитата Akina @
Не, фигня получится - на показанных данных такой запрос вернёт ещё и ProductID=4, у которого AttrId = 8 имеет значение AttrValueId = 331.

Согласен. Я невнимательно прочел условие. Тогда альтернативный вариант запроса:

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    SELECT
      A.ProductId
    FROM
      ProductTable AS A
    LEFT JOIN
      ProductTable AS B
        ON A.ProductId = B.ProductId
    WHERE
      (A.AttrId = 5 AND A.AttrValueId = 1010) AND (B.AttrId = 8 AND B.AttrValueId = 352)

Какой из запросов будет лучше - я без понятия.

Автор: Костик+ 18.07.23, 14:06
Простите за отложенный ответ. Majestio, Akina, спасибо вам, что уделили время и помогли мне.
Вот примерно такой синтаксис я и искал, в своей практике не встреч. Но, загуглив, нашёл ключевые слова для поиска "WHERE IS multicolumn". Буду читать, разбираться.
Попробовал на MSSQL - ругается, мол такой синтаксис не понимает. Попробую ещё на MySQL/MariaDB для сравнения, проверю и отпишу чуть позже.

Ещё раз, всем - спасибо!

Автор: Akina 18.07.23, 18:23
Если гуглить - то по термину "логическое деление"..

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