简体   繁体   中英

SQL Count returns wrong value in my INNER JOIN Statement

I am quite new to SQL and I am having some difficulty with my COUNT() feature.

It keeps returning the wrong COUNT() value as I am trying to calculate the TOTAL number of specific cars sold by users. My tables and results are here: http://sqlfiddle.com/#!9/d2ef0/5

My Schema:

CREATE TABLE IF NOT EXISTS Users(
    userID INT NOT NULL AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    forename VARCHAR(50) NOT NULL,
    surname VARCHAR(50) NOT NULL,
    PRIMARY KEY (userID)
);

CREATE TABLE IF NOT EXISTS CarType(
    carTypeID INT NOT NULL AUTO_INCREMENT,
    description VARCHAR(80),
    PRIMARY KEY (carTypeID)
);  

CREATE TABLE IF NOT EXISTS Country(
    countryID INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(100),
    PRIMARY KEY (countryID)
);  

CREATE TABLE IF NOT EXISTS Cars(
    carID INT NOT NULL AUTO_INCREMENT,
    carTypeID INT NOT NULL,
    countryID INT NOT NULL,
    description VARCHAR(100) NOT NULL,
    make VARCHAR(100) NOT NULL,
    model VARCHAR(100),
    FOREIGN KEY (carTypeID) REFERENCES CarType(carTypeID),
    FOREIGN KEY (countryID) REFERENCES Country(countryID),
    PRIMARY KEY (carID)
);

CREATE TABLE IF NOT EXISTS Likes(
    userID INT NOT NULL,
    carID INT NOT NULL,
    likes DOUBLE NOT NULL,
    FOREIGN KEY (userID) REFERENCES Users(userID),
    FOREIGN KEY (carID) REFERENCES Cars(carID)
);

CREATE TABLE IF NOT EXISTS Sold(
    userID INT NOT NULL,
    carID INT NOT NULL,
    FOREIGN KEY (userID) REFERENCES Users(userID),
    FOREIGN KEY (carID) REFERENCES Cars(carID)
);

INSERT INTO Users VALUES 
(NULL, "micheal", "Micheal", "Sco"),
(NULL, "bensco", "Ben", "Sco"),
(NULL, "shanemill", "Shane", "Miller");

INSERT INTO CarType VALUES
(NULL, "Saloon"),
(NULL, "HatchBack"),
(NULL, "Low Rider");

INSERT INTO Country VALUES
(NULL, "UK"),
(NULL, "USA"),
(NULL, "JAPAN"),
(NULL, "GERMANY");

INSERT INTO Cars VALUES
(NULL, 1, 2, "Ford Mustang lovers", "Mustang", "Ford"),
(NULL, 2, 3, "Drift Kings", "Skyline", "Nissan"),
(NULL, 3, 1, "British classic", "Cooper", "Mini");

INSERT INTO Likes VALUES
(1, 1, 3),
(1, 2, 2),
(2, 3, 5),
(2, 3, 7),
(2, 3, 1),
(2, 3, 2);

INSERT INTO Sold VALUES
(1, 2),
(1, 3),
(1, 1),
(2, 2),
(2, 3),
(3, 1),
(3, 3);

This is the Sold table:

userID  carID
  1      2
  1      3
  1      1
  2      2
  2      3
  3      1
  3      3

This is my complex query:

SELECT DISTINCT Cars.carID, Cars.description, Cars.model, Country.name, 
CarType.description, ROUND(AVG(Likes.likes)), COUNT(*)
FROM Cars
INNER JOIN Sold ON
Cars.carID = Sold.carID
INNER JOIN Country ON
Cars.countryID = Country.countryID
INNER JOIN CarType ON
Cars.carTypeID = CarType.carTypeID
INNER JOIN Likes ON
Cars.carID = Likes.carID
GROUP BY Cars.carID

The actual result from this complex SQL Query :

carID   description             model       name    description     ROUND(AVG(Likes.likes))     COUNT(*)
1       Ford Mustang lovers     Ford        USA     Saloon              3                           2
2       Drift Kings             Nissan      JAPAN   HatchBack           2                           2
3       British classic         Mini        UK      Low Rider           4                           12

For example, the result for the last one is incorrect - it should not be 12

Would be nice if someone could tell me where I went wrong

Thanks

You are attempting to aggregate across two different dimensions -- Sold and Likes . The result is a Cartesian product of rows for each car, and this throws off the aggregations.

The solution is the pre-aggregate the results along each dimension:

SELECT c.carID, c.description, c.model, cy.name, ct.description,
       l.avgLikes, s.NumSold
FROM Cars c INNER JOIN
     (SELECT s.CarId, COUNT(*) as NumSold
      FROM Sold s
      GROUP BY s.CarId
     ) s
     ON c.carID = s.carID INNER JOIN
     Country cy
     ON c.countryID = cy.countryID INNER JOIN
     CarType ct
     ON c.carTypeID = ct.carTypeID LEFT JOIN
     (SELECT l.carId, AVG(Likes) as avgLikes
      FROM Likes l
      GROUP BY CarId
     ) l
     ON c.carID = l.carID;

Here is the SQL Fiddle.

If all you want is the total number of specific cars sold by user then all your info is in the sold table. This query will give you what you want by carID. You can use that as a subquery if you want to join on other tables to get more info.

SELECT userID, carID, count(*) as totalSold FROM Sold GROUP BY userID, carID;

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