На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! информация о разделе
user posted imageДанный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ.

Модераторы: Akina
  
> Необходима помощь с составлением SQL-запроса
    Доброго времени суток, всем!
    Собственно, сабж.

    Есть таблица вида:
    ExpandedWrap disabled
      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

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


    В результате выполнения подобного запроса для таблицы из примера выше, получим выборку:
    ExpandedWrap disabled
      ProductId
      ----------
      1
      3


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

    БД: MSSQL.

    Надеюсь, правильно сформулировал свою мысль.
    Сообщение отредактировано: Костик+ -
      Цитата Костик+ @
      Каждый ProductId может иметь только один AttrId.

      В таблице ProductId = 1 имеет пять AttrId ... дальше не читал :)
        ExpandedWrap disabled
          SELECT ProductID
          FROM ProductTable
          WHERE ( AttrId, AttrValueId ) IN ( (5, 1010), (8, 352) )
          GROUP BY ProductID
          HAVING COUNT( /* DISTINCT */ AttrId ) = 2
          Цитата Majestio @
          В таблице ProductId = 1 имеет пять AttrId ... дальше не читал

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

          может быть, а:
          ExpandedWrap disabled
            ProductId | AttrId
            ----------+--------
            1         |4
            1         |4
            1         |4

          не может.
            Цитата Костик+ @
            Т.е., получается что-то типа такого:

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

            ExpandedWrap disabled
              SELECT
                ProductID
              FROM
                ProductTable
              WHERE
                (AttrId = 5 AND AttrValueId = 1010)
                OR -- <--- тут
                (AttrId = 8 AND AttrValueId = 352)
              Цитата Majestio @
              В операторе WHERE собирай условия не по "и", а по "или", и всё получится

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

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

                ExpandedWrap disabled
                  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)

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

                  Ещё раз, всем - спасибо!
                    Если гуглить - то по термину "логическое деление"..
                    0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                    0 пользователей:


                    Рейтинг@Mail.ru
                    [ Script execution time: 0,0373 ]   [ 15 queries used ]   [ Generated: 27.04.24, 10:36 GMT ]