skip to Main Content

I am trying to query the code, name, and the number of rentals of customers who have made at least ten rentals.

My query:

Select client.ClientCode, client.ClientNom, (location.LocationRef)
FROM client
  INNER JOIN location ON client.ClientCode = location.ClientCode
WHERE location.LocationRef > 9
GROUP BY location.ClientCode;

Output:

ClientCode | ClientNom | LocationRef
-----------+-----------+------------
12874      | Alex      | 10

It doesn’t work. It shows me the first LocationRef beyond 10 but not the number of rentals made by the client.

I test with a COUNT in my query :

SELECT client.ClientCode, client.ClientNom, Count(location.LocationRef) 
  FROM client 
    INNER JOIN location 
      ON client.ClientCode = location.ClientCode WHERE location.LocationRef > 9 
GROUP BY location.ClientCode;

This is what i got :

ClientCode | ClientNom | Count(location.locationRef)
-----------+-----------+----------------------------
12874      | Alex      | 5

This is not what I want, because my client has made 13 rentals and it only shows me the number of rentals beyond the 9th rental.

Script to install my database:

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;

SET time_zone = "+00:00";

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

CREATE TABLE `client` (
  `ClientCode` int(11) NOT NULL,
  `ClientNom` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `client` (`ClientCode`, `ClientNom`) VALUES
(123, 'Gaetan'),
(12874, 'Alex'),
(12875, 'Max');

CREATE TABLE `location` (
  `LocationRef` int(11) NOT NULL,
  `Immatriculation` varchar(11) NOT NULL,
  `ClientCode` int(11) NOT NULL,
  `MontantLocation` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `location` (`LocationRef`, `Immatriculation`, `ClientCode`, `MontantLocation`) VALUES
(1, 'AA-229-AA', 12874, 123), (2, 'AA-229-AB', 12875, 156),
(3, 'BA-229-AA', 12874, 700), (4, 'AB-229-AA', 12874, 678),
(5, 'AA-229-AB', 12874, 987), (6, 'AA-229-AB', 12874, 980),
(7, 'AB-229-AA', 12874, 567), (8, 'AA-229-AA', 12874, 7789),
(9, 'AA-229-AB', 12874, 567), (10, 'AA-229-AB', 12874, 456),
(11, 'AA-229-AA', 12874, 566), (12, 'AB-229-AA', 12874, 700),
(13, 'AA-229-AA', 12874, 899), (14, 'AA-229-AB', 12874, 67);

2

Answers


  1. Start with a subquery to find all the ClientCode values that have ten or more items in your location table. The aggregating subquery does the counting.

                    SELECT ClientCode
                      FROM location
                     GROUP BY ClientCode
                    HAVING COUNT(*) >= 10
    

    Then INNER JOIN that subquery in your main query to filter out all but the frequent customers.

    SELECT client.ClientCode, client.ClientNom, (location.LocationRef)
      FROM client
     INNER JOIN location ON client.ClientCode = location.ClientCode
     INNER JOIN (
                     SELECT ClientCode
                       FROM location
                      GROUP BY ClientCode
                    HAVING COUNT(*) >= 10
    ) frequent_clients  ON client.ClientCode = frequent_clients.ClientCode;
    

    If you want just one row per client in your result set, try this

    SELECT client.ClientCode, client.ClientNom, COUNT(*) number_of_rentals
      FROM client
     INNER JOIN location ON client.ClientCode = location.ClientCode
     INNER JOIN (
                     SELECT ClientCode
                       FROM location
                      GROUP BY ClientCode
                    HAVING COUNT(*) >= 10
        ) frequent_clients
              ON client.ClientCode = frequent_clients.ClientCode
    GROUP BY client.ClientCode, client.ClientNom
    

    Fiddle here.

    Login or Signup to reply.
  2. The query condition WHERE location.LocationRef > 9 is not doing what you expect. It’s limiting your query to only access the 10th and later entries into the location table. Entries where LocationRef equals 1 – 9 are ignored.

    And Count(location.LocationRef) is in the wrong part of the query.


    Rather, put the COUNT and GROUP BY in an ad hoc, temporary table querying the location table, INNER JOIN‘ed with the client table, to get client information and count how many records there are over a certain number of client records, then limit the querying of client information to only those who have at least 10 entries:

    SELECT loc.ClientCode, loc.cnt, client.ClientNom 
      FROM client 
        INNER JOIN (
          SELECT ClientCode, COUNT(ClientCode) cnt 
            FROM location 
            GROUP BY clientCode
        ) loc ON client.ClientCode = loc.ClientCode
      WHERE loc.cnt > 9 /* at least 10 entries */
    ;
    

    Output:

    ClientCode | cnt | ClientNom
    -----------+-----+----------
    12874      | 13  | Alex
    

    The temporary table query:

    SELECT ClientCode, COUNT(ClientCode) cnt 
      FROM location 
      GROUP BY clientCode
    

    …uses a combination of COUNT AND GROUP BY to determine how many records there are for each ClientCode.

    And results in the output:

    ClientCode | cnt
    -----------+----
    12874      | 13
    12875      | 1
    

    Now this becomes the temporary table that can be INNER JOIN‘ed with the client table, using the ClientCode field, to get the client information: ON client.ClientCode = loc.ClientCode.

    Also the calculated field COUNT(ClientCode), in the temp table query, is aliased cnt for access outside the temp table query, as in: loc.cnt and WHERE loc.cnt > 9.

    The temporary table must be named. That name is then used to access it’s values outside of the temporary table query itself:

    INNER JOIN ( /* temp query here */ ) loc ON client.ClientCode = loc.ClientCode
    

    In this case using the name loc and referencing fields like this: loc.ClientCode.

    And, finally, it’s the primary query, or outside query, where the results are limited to only those clients with a count (cnt) of more than 9 (at least 10) entries in the loc table:

    SELECT loc.ClientCode, loc.cnt, client.ClientNom
      FROM client
      /* INNER JOIN here, named loc */
    WHERE loc.cnt > 9
    

    Try it here: https://onecompiler.com/mysql/3yfwuunrs

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search