Brian Lee
Brian Lee

Reputation: 57

SQL COUNT NULL values

I am trying to find the Playlist(s) with 10 or more tracks that have NULL values in the Composer column.

Here are the tables

CREATE TABLE [Playlist]
(
[PlaylistId] INTEGER  NOT NULL,
[Name] NVARCHAR(120),
CONSTRAINT [PK_Playlist] PRIMARY KEY  ([PlaylistId])
);

CREATE TABLE [PlaylistTrack]
(
[PlaylistId] INTEGER  NOT NULL,
[TrackId] INTEGER  NOT NULL,
CONSTRAINT [PK_PlaylistTrack] PRIMARY KEY  ([PlaylistId], [TrackId]),
FOREIGN KEY ([PlaylistId]) REFERENCES [Playlist] ([PlaylistId]) 
    ON DELETE NO ACTION ON UPDATE NO ACTION,
FOREIGN KEY ([TrackId]) REFERENCES [Track] ([TrackId]) 
    ON DELETE NO ACTION ON UPDATE NO ACTION
);

CREATE TABLE [Track]
(
[TrackId] INTEGER  NOT NULL,
[Name] NVARCHAR(200)  NOT NULL,
[AlbumId] INTEGER,
[MediaTypeId] INTEGER  NOT NULL,
[GenreId] INTEGER,
[Composer] NVARCHAR(220),
[Milliseconds] INTEGER  NOT NULL,
[Bytes] INTEGER,
[UnitPrice] NUMERIC(10,2)  NOT NULL,
CONSTRAINT [PK_Track] PRIMARY KEY  ([TrackId]),
FOREIGN KEY ([AlbumId]) REFERENCES [Album] ([AlbumId]) 
    ON DELETE NO ACTION ON UPDATE NO ACTION,
FOREIGN KEY ([GenreId]) REFERENCES [Genre] ([GenreId]) 
    ON DELETE NO ACTION ON UPDATE NO ACTION,
FOREIGN KEY ([MediaTypeId]) REFERENCES [MediaType] ([MediaTypeId]) 
    ON DELETE NO ACTION ON UPDATE NO ACTION
)

Here is what I have so far. I think the query logic is good but is this the correct way to count up null values?

SELECT P.PlaylistId, P.name
FROM Playlist P
    JOIN PlaylistTrack pt ON p.PlaylistId = pt.PlaylistId
    JOIN Track t ON pt.TrackId = t.TrackId
GROUP BY p.PlaylistId
HAVING COUNT(t.Composer IS NULL) >=10;

Upvotes: 1

Views: 1402

Answers (3)

Tom H
Tom H

Reputation: 47464

Trying to compare COUNT(T.Compser) >= 10 in the SELECT clause is a mistake. That's a comparison that is going to (always) return a true/false. That subquery also has no relation to your outer query. I'm actually surprised that it even runs without an error.

You should be able to use the HAVING clause, which is used to compare aggregates:

SELECT
    P.PlaylistID,
    P.Name
FROM
    Playlist P
INNER JOIN PlaylistTrack PT ON PT.PlaylistID = P.PlaylistID
INNER JOIN Track T ON
    T.TrackID = PT.TrackID AND
    T.Composer IS NULL
GROUP BY
    P.PlaylistID,
    P.Name
HAVING
    COUNT(*) >= 10

EDIT: You've changed your question. With the new query, the problem is that COUNT() will always count a row regardless of what the value is inside unless that value is NULL. T.Composer IS NULL will evaluate to a value - either true or false (1/0), which means that regardless of the value of T.Composer, every row will be counted towards the aggregate.

Upvotes: 1

user5283058
user5283058

Reputation:

I would use left join instead of inner. This way it will still return a row even if there are no rows within that query. Sometimes this has a chance to break your statement since it can't count null.

Upvotes: 0

Malbordio
Malbordio

Reputation: 92

Instead of NULL, can't you just state something like <> 0 ? or = 0 ?

or at least try:

Where T.Composer IS NULL or col = ''

or Where T.Composer IsNull(col, '') = ''

Upvotes: 0

Related Questions