简体   繁体   中英

Using 1 Query to Display COUNT(Items) in a Column and COUNT(Same Item, but With Certain Value in Another Column)

Thanks in advance for the assistance!

I have three tables in a dummy database: inventory, film, and rental.

I need to know which film titles are not in the inventory. The only way to answer this that I can think of is by counting each item in the inventory and then comparing that count to the number of the same item that haven't been returned.

This returns three columns:


    SELECT film.title, COUNT(inventory.film_id), (SELECT COUNT(inventory.film_id)
                                                  FROM inventory
                                                  INNER JOIN rental ON rental.inventory_id = inventory.inventory_id
                                                  INNER JOIN film on film.film_id = inventory.film_id
                                                  WHERE rental.return_date IS NULL)
    FROM inventory
    INNER JOIN rental ON rental.inventory_id = inventory.inventory_id
    INNER JOIN film on film.film_id = inventory.film_id
    GROUP BY film.title

Output:

"Graceland Dynamite"    "6" "183"
"Opus Ice"  "11"    "183"
"Braveheart Human"  "5" "183"
"Wonderful Drop"    "9" "183"
...

As you can see, it shows me in the last column the TOTAL number of non-returned DVD's, while I want the total for that column.

If I run it and just look for the inventory count like so:

    SELECT film.title, COUNT(inventory.film_id)
    FROM inventory
    INNER JOIN rental ON rental.inventory_id = inventory.inventory_id
    INNER JOIN film on film.film_id = inventory.film_id
    GROUP BY film.title

That works:

"Graceland Dynamite"    "6"
"Opus Ice"  "11"
"Braveheart Human"  "5"
...

And if I run the same thing but counting only the inventory that has a NULL return date:


    SELECT film.title, COUNT(inventory.film_id), rental.return_date
    FROM inventory
    INNER JOIN rental ON rental.inventory_id = inventory.inventory_id
    INNER JOIN film on film.film_id = inventory.film_id
    WHERE rental.return_date IS NULL
    GROUP BY film.title, rental.return_date

That works too:

"Theory Mermaid"    "1" 
"Dances None"   "2" 
"Bound Cheaper" "1" 
...

Please let me know if you can help me understand how to return the inventory count in one column and also the count of the non-returned items, and bonus points if you can tell me how to have a column that shows the difference between the two.

Also if there's a way to return only the rows where the difference is zero, that would be cool.

OR if I'm just thinking about this all wrong let me know too. I need all the help I can get.

Thanks!!

UPDATE:

I tried it like this too:


    SELECT film.title, COUNT(inventory.film_id), x.copies_out
    FROM (SELECT COUNT(rental.inventory_id) as copies_out
          FROM rental
          WHERE rental.return_date IS NULL) as x, inventory
    INNER JOIN film ON film.film_id = inventory.film_id
    INNER JOIN rental ON rental.inventory_id = inventory.inventory_id
    GROUP BY film.title, x.copies_out, rental.inventory_id
    HAVING COUNT(inventory.film_id) <= x.copies_out

This returns me 3 columns, one with the film title, one with the number of total copies listed in inventory, and one with the total number of rentals that still have not been returned (not the number of rentals with that inventory ID that haven't been returned yet.)

"Giant Troopers"    "5" "183"
"Confessions Maguire"   "2" "183"
"Vacation Boondock" "3" "183"

Please help! -Pete

I think you are looking for a conditional aggregation using the filter clause:

SELECT film.title, 
       count(inventory.film_id), 
       count(distinct rental.inventory_id) filter (where rental.return_date is null) 
FROM inventory
  INNER JOIN rental ON rental.inventory_id = inventory.inventory_id
  INNER JOIN film on film.film_id = inventory.film_id
GROUP BY film.title;

I need to know which film titles are not in the inventory.

This sounds like not exists :

select f.*
from films f
where not exists (select 1
                  from inventory i
                  where i.film_id = f.film_id
                 );

The rental table is not needed for this query.

If you need the rental table to identify films in the inventory, then you cannot answer your question. The closest you can come is "What films have not been rented?" That would be:

select f.*
from films f
where not exists (select 1
                  from inventory i join
                       rental r
                       on i.inventory_id = r.inventory_id
                  where r.film_id = f.film_id
                 );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM