Як отримати групу, де кількість дорівнює нулю?


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, ви повинні порахувати стовпець із внутрішньої таблиці (ви рахуєте з зовнішньої таблиці), яка, як відомо, не визначається як НУЛІ (щоб мати можливість розрізняють NULL в даних і NULL, створені Зовнішнім приєднанням). Найпростіший спосіб - порахувати стовпчик приєднання:COUNT(u.streetid)
dnoeth

Тому що right joinі right outer joinце ті самі речі. Я додав пояснення у свою відповідь, як це запропонував @ jpmc26.
SqlWorldWide

Відповіді:


18

Причина, коли ваш запит не працював за призначенням:

Внутрішнє з'єднання дає вам перетин 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

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


2
Для мене перехід від count (*) до count (customer.id) - аналогічно показаному вище - зробив критичну різницю. Дякую :)
Zeek

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 як нульове значення

Ось короткий запит:

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.