简体   繁体   中英

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;

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.

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, '') = ''

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.

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