Как получить группу, где счетчик равен нулю?


12

Я постараюсь составить график из данных из моей базы данных SQL-сервера. У меня будут все улицы с количеством пользователей, которые живут на этой улице, даже если счет равен нулю.

Для этого я пробовал этот запрос:

Create table Streets(
  ID int IDENTITY  primary key,
  Name varchar(100)
);

create table users(
  ID int IDENTITY  primary key,
  Username varchar(100),
  StreetID int references Streets(id)
);

insert into streets values ('1st street'), ('2nd street'), ('3rd street'), 
                           ('4th street'), ('5th street');
insert into users values ('Pol', 1), ('Doortje', 1), ('Marc', 2), ('Bieke', 2), 
                         ('Paulien', 2), ('Fernand', 2), ('Pascal', 2), ('Boma', 3), 
                         ('Goedele', 3), ('Xavier', 4);

select s.name as street, count(s.name) as count 
from users u inner join streets s on u.streetid = s.id
group by s.name

И это дает мне такой вывод:

|   | street     | count |
| - | ---------- | ----- |
| 1 | 1st street | 2     |
| 2 | 2nd street | 5     |
| 3 | 3rd street | 2     |
| 4 | 4th street | 1     |

Проблема в том, что 5-я улица, где нет пользователей, не появляется в результате. Могу ли я сделать это с сервером SQL? Здесь у вас есть скрипка

Обновление: если я это сделаю right join, я получу этот результат:

|   | street     | count |
| - | ---------- | ----- |
| 1 | 1st street | 2     |
| 2 | 2nd street | 5     |
| 3 | 3rd street | 2     |
| 4 | 4th street | 1     |
| 5 | 5th street | 1     | 

Смотри эту скрипку.


4
Как никто не объяснил, почему ваш запрос не возвращает ожидаемый результат: поскольку агрегатная функция игнорирует NULL, вы должны считать столбец из внутренней таблицы (вы считали из внешней таблицы), который, как известно, определяется как NOT NULL (чтобы иметь возможность различать значения NULL в данных и значения NULL, создаваемые внешним соединением). Самый простой способ подсчитать присоединиться к колонку:COUNT(u.streetid)
dnoeth

Потому что right joinи right outer joinэто одно и то же. Я добавил в свой ответ объяснение, предложенное @ jpmc26.
SqlWorldWide

Ответы:


17

Причина, по которой ваш запрос не сработал как задумано:

Внутреннее соединение дает вам пересечение 2 таблиц. В вашем случае 5th streetв вашей таблице пользователей не было записи для, и поэтому объединение не создавало для этого никакой записи.

Внешнее соединение (правое или левое) даст результат внутреннего соединения и, кроме того, все неквалифицирующие записи из левой или правой таблицы в зависимости от типа (левого или правого) внешнего соединения.

В этом случае я поместил улицу слева от объединения и использовал левое внешнее объединение, так как вы хотели, чтобы все улицы (даже счетчик был равен нулю) в вашем наборе результатов.

Измените ваш запрос выбора на это.

SELECT S.Name AS Street,
       Count(U.Username) AS COUNT
FROM Streets S
LEFT OUTER JOIN Users U ON U.Streetid = S.Id
GROUP BY S.Name

Результат введите описание изображения здесь


1
Для меня изменение количества (*) на количество (customer.id) - как показано выше - имело решающее значение. Спасибо :)
Зик

9

Это один из возможных способов.

select s.name as streets,
       (select count(*)
        from   users
        where  StreetID = s.id) cnt
from   streets s;

7

Очистка кода для работы с чувствительным к регистру экземпляром ...

CREATE TABLE Streets
(
    ID INT IDENTITY PRIMARY KEY,
    Name VARCHAR(100)
);

CREATE TABLE users
(
    ID INT IDENTITY PRIMARY KEY,
    Username VARCHAR(100),
    StreetID INT
        REFERENCES Streets ( ID )
);

INSERT INTO Streets
VALUES ( '1st street' ),
    ( '2nd street' ),
    ( '3rd street' ),
    ( '4th street' ),
    ( '5th street' );
INSERT INTO users
VALUES ( 'Pol', 1 ),
    ( 'Doortje', 1 ),
    ( 'Marc', 2 ),
    ( 'Bieke', 2 ),
    ( 'Paulien', 2 ),
    ( 'Fernand', 2 ),
    ( 'Pascal', 2 ),
    ( 'Boma', 3 ),
    ( 'Goedele', 3 ),
    ( 'Xavier', 4 );

Когда вы используете COUNTс именем столбца, он считает NOT NULLзначения.

Я использую RIGHT JOINздесь, чтобы успокоить Джо Оббиш.

SELECT   s.Name AS street, COUNT(u.Username) AS count
FROM     users AS u
RIGHT JOIN Streets AS s
ON u.StreetID = s.ID
GROUP BY s.Name

Полученные результаты:

street      count
1st street  2
2nd street  5
3rd street  2
4th street  1
5th street  0

0
  1. Получить счет по идентификатору улицы
  2. присоединиться к идентификатору улицы с идентификатором с улиц
  3. Используйте Coalsesce в качестве значения NULL

Вот краткий запрос:

select Name, coalesce( u.ct,0)ct FROM streets s left join (
select StreetID,count(*)ct from users group by StreetID)u on s.ID=u.StreetID

То есть с левым соединением
ракеш
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.