Подсчет количества повторяющихся строк после инструкции multi join

#sql #sql-server

#sql #sql-сервер

Вопрос:

У меня есть три таблицы, из которых мне нужно получить информацию: Products, ProductOptions и OptionChoices. На данный момент это SQL, который я использую для получения указанной информации

 select P.ProductId,P.Name,P.StoreId,PO.OptionId,OC.ChoiceName from Products P
inner join ProductOptions PO on P.ProductId=PO.ProductID
inner join OptionChoices OC on PO.OptionId=OC.OptionId
where P.ProductId=23317
  

который выводит это:

 ProductId   Name               StoreID OptionId ChoiceName
23317   Admiral Ackbar Cereal   629     795      fish
23317   Admiral Ackbar Cereal   629     795      shrimp
23317   Admiral Ackbar Cereal   629     795      traps
23317   Admiral Ackbar Cereal   629     797      box
23317   Admiral Ackbar Cereal   629     797      casket
  

Что сделало бы мою жизнь намного проще, если бы я мог добавить еще один столбец, который дал бы мне общее количество вариантов для каждого идентификатора параметра. Таким образом, первая строка будет читать:

 ProductId   Name               StoreID OptionId ChoiceName  Count
23317   Admiral Ackbar Cereal   629     795      fish         3
  

Потому что есть 3 варианта с 795 в качестве идентификаторов опций. Я пробовал использовать различные комбинации group by и count, но безуспешно. У кого-нибудь есть идеи, чтобы указать мне правильное направление?

Редактировать: я использую SQL Server

Комментарии:

1. Какую версию SQL вы используете?

2. SQL server. Просто обновил мой вопрос

Ответ №1:

Вам нужен отдельный запрос для подсчета параметров. В этом примере MS SQL SERVER я использую коррелированный подзапрос для подсчета.

 SELECT
  P.ProductId,
  P.Name,
  P.StoreId,
  PO.OptionId,
  OC.ChoiceName,
  (SELECT COUNT(*) FROM OptionChoices WHERE OptionId = OC.OptionId) AS option_count
FROM
  Products   P
INNER JOIN
  ProductOptions PO
    ON P.ProductId = PO.ProductID
INNER JOIN
  OptionChoices  OC
    ON PO.OptionId = OC.OptionId    
WHERE
  P.ProductId=23317
  

Комментарии:

1. Это полностью сработало. Спасибо! Я собираюсь потратить некоторое время на чтение этого запроса, чтобы понять это.

2. Проблемы с производительностью будут полностью зависеть от индексации и размера рассматриваемого набора данных. Как и в этом запросе P.ProductId=23317 , коррелированный подзапрос действительно будет иметь отношение только к небольшому количеству записей. Также обратите внимание, что SQL Server довольно хорошо оптимизирует это. Тем не менее, объединение (SELECT OptionID, COUNT(*) FROM OptionChoices GROUP BY OptionID) будет быстрее для больших наборов данных.

3. Это не для чего-либо, связанного с производством. Мне нужно сгенерировать несколько отчетов, и это просто помогает мне быстрее выполнить задачу.

Ответ №2:

Вы так близко…

Выполните:

 Select p.Productid, p.name,     
P.storeid,P.optionid, Count(choicename) 
From ( your actual query here) p
Group by p.productid,p.name,p.storeid,p.optionid
  

Комментарии:

1. Это удаляет option_name из результирующего набора. Оператору требуется каждая запись вместе с количеством записей в группе…

2. Столбец ‘OptionChoices.Name ‘ недопустимо в списке выбора, поскольку оно не содержится ни в агрегатной функции, ни в предложении GROUP BY.

3. Уважаемые коллеги, я написал свое заявление из ячейки, и в мобильной версии довольно сложно увидеть все это целиком, если требуется значение option_name, то его следует выбрать; если повторяющиеся значения нежелательны, то они должны быть сгруппированы по этому столбцу. Идея состоит в том, чтобы выбрать все повторяющиеся столбцы и подсчитать те, которые не повторяются, группируя по всем тем, которые не включены в счетчик.

4. Оператору требуется каждый элемент в наборе, без группировки, удаления дублирования или любой другой функциональности. Затем в качестве дополнительного поля требуется количество подгрупп. Этого нельзя достичь только одной ссылкой на таблицу OptionChoices.

5. @dems тогда я допустил ошибку, я думал, что ему нужны только отдельные столбцы количество вариантов для одного и того же продукта.

Ответ №3:

Попробуйте это 🙂

 select P.ProductId,P.Name,P.StoreId, PO.OptionId, max(OC.ChoiceName), count(P.ProductId) from Products P
inner join ProductOptions PO on P.ProductId=PO.ProductID
inner join OptionChoices OC on PO.OptionId=OC.OptionId
where P.ProductId=23317
GROUP BY P.ProductId, PO.OptionId 
  

проблема в том, что вы не знаете, что вы получаете для поля «OC.ChoiceName» — вы также можете использовать GROUP_CONCAT (OC.ChoiceName)

смотрите: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

Результат для max:

 ProductId   Name               StoreID OptionId ChoiceName  Count
23317   Admiral Ackbar Cereal   629     795      traps        3
23317   Admiral Ackbar Cereal   629     797      box          2
  

Результат для GROUP_CONCAT (только MySQL !!):

 ProductId   Name               StoreID OptionId ChoiceName           Count
23317   Admiral Ackbar Cereal   629     795      fish,shrimp,traps      3
23317   Admiral Ackbar Cereal   629     797      box,casket             2
  

Комментарии:

1. Облом, получаю ошибки для каждого. Для первого: столбец «Продукты. ProductID’ недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY . Для второго: неправильный синтаксис рядом с ‘GROUP_CONCAT’. Использование Sql server, если это помогает

2. GROUP_CONCAT — это MySQL — Извините — забыл «P.» и «PO». в «GROUP BY» — попробуйте еще раз

Ответ №4:

 select
      P.ProductId
    , P.Name
    , P.StoreId
    , PO.OptionId
    , OC.ChoiceName
    , count(PO.OptionId) over (partition by P.StoreId) as OpCount
from Products P
inner join ProductOptions PO on P.ProductId = PO.ProductID
inner join OptionChoices OC  on PO.OptionId = OC.OptionId
where P.ProductId = 23317