Oracle SQL Как считать значения столбцов и Group BY при объединениях - PullRequest
0 голосов
/ 17 декабря 2018

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

Показать всех клиентов, которые проверили больше книг, чем DVD.Показать имя клиента, общее количество оформленных заказов и общее количество проверок на DVD.Сортировать результаты по имени и фамилии клиента.

SELECT C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, COUNT(T.TRANSACTION_ID)
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
INNER JOIN catalog_item CT ON P.CATALOG_ITEM_ID = CT.CATALOG_ITEM_ID 
GROUP BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME
ORDER BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME;

Выполнить сначала: https://drive.google.com/open?id=1PYAZV4KIfZtxP4eQn35zsczySsxDM7ls

Выполнить секунду: https://drive.google.com/open?id=1pAzWmJqvD3o3n6YJqVUM6TtxDafKGd3f

РЕДАКТИРОВАТЬ
С некоторой помощью мистера Барбароса я пришел к следующему запросу, который ближе.Однако этот запрос не возвращает никаких результатов для DVD-дисков, поэтому я считаю, что это проблема объединения.

SELECT C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, COUNT(CT1.TYPE) AS BOOK_COUNT, COUNT(CT2.TYPE) AS DVD_COUNT
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
INNER JOIN catalog_item CT1 ON P.CATALOG_ITEM_ID = CT1.CATALOG_ITEM_ID AND CT1.TYPE = 'BOOK'
LEFT OUTER JOIN catalog_item CT2 ON P.CATALOG_ITEM_ID = CT2.CATALOG_ITEM_ID AND CT2.TYPE = 'DVD'
GROUP BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, CT1.TYPE, CT2.TYPE
ORDER BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME;

Ответы [ 3 ]

0 голосов
/ 17 декабря 2018

Использовать «условные агрегаты» (используйте выражение регистра внутри функции агрегата)

SELECT
    C.CUSTOMER_FIRSTNAME
  , C.CUSTOMER_LASTNAME
  , COUNT( CASE WHEN CT.TYPE = 'BOOK' THEN T.TRANSACTION_ID END ) books
  , COUNT( CASE WHEN CT.TYPE = 'DVD' THEN T.TRANSACTION_ID END ) dvds
FROM customer C
INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
INNER JOIN catalog_item CT ON P.CATALOG_ITEM_ID = CT.CATALOG_ITEM_ID
GROUP BY
    C.CUSTOMER_FIRSTNAME
  , C.CUSTOMER_LASTNAME
HAVING
     COUNT( CASE WHEN CT.TYPE = 'BOOK' THEN T.TRANSACTION_ID END ) 
   > COUNT( CASE WHEN CT.TYPE = 'DVD' THEN T.TRANSACTION_ID END )
ORDER BY
    C.CUSTOMER_FIRSTNAME
  , C.CUSTOMER_LASTNAME
;
0 голосов
/ 17 декабря 2018

Пожалуйста, попробуйте удалить , CT1.TYPE, CT2.TYPE в вашей группе по предложению.

0 голосов
/ 17 декабря 2018

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

SELECT C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME, 
       COUNT(CT1.CATALOG_ITEM_ID) as "Book Checkout", 
       COUNT(CT2.CATALOG_ITEM_ID) as "DVD Checkout"
  FROM customer C
 INNER JOIN library_card LC ON C.CUSTOMER_ID = LC.CUSTOMER_ID
 INNER JOIN transaction T ON LC.LIBRARY_CARD_ID = T.LIBRARY_CARD_ID
 INNER JOIN physical_item P ON T.PHYSICAL_ITEM_ID = P.PHYSICAL_ITEM_ID
  LEFT JOIN catalog_item CT1 ON P.CATALOG_ITEM_ID = CT1.CATALOG_ITEM_ID AND CT1.TYPE = 'BOOK'
  LEFT JOIN catalog_item CT2 ON P.CATALOG_ITEM_ID = CT2.CATALOG_ITEM_ID AND CT1.TYPE = 'DVD'
 GROUP BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME
HAVING COUNT(CT1.CATALOG_ITEM_ID) > COUNT(CT2.CATALOG_ITEM_ID)
 ORDER BY C.CUSTOMER_FIRSTNAME, C.CUSTOMER_LASTNAME;

CUSTOMER_FIRSTNAME  CUSTOMER_LASTNAME   Book Checkout  DVD Checkout
------------------  -----------------   -------------  -------------
Deena               Pilgrim                   3              1
Emile               Cross                     5              2
...