Jak zdobyć grupę, w której liczba wynosi zero?

12

Spróbuję utworzyć wykres z danych z mojej bazy danych serwera SQL. Będę mieć wszystkie ulice z liczbą użytkowników, którzy mieszkają na tej ulicy, nawet liczba jest równa zero.

W tym celu wypróbowałem następujące zapytanie:

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

I daje mi to:

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

Problem polega na tym, że 5. ulica, na której nie mieszka żaden użytkownik, nie pojawia się w wyniku. Czy mogę to zrobić z serwerem SQL? Masz skrzypce

Aktualizacja: jeśli tak right join, mam ten wynik:

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

Zobacz to skrzypce.

H. Pauwelyn
źródło
4
Jak nikt nie wyjaśnił, dlaczego zapytanie nie zwraca oczekiwanego wyniku: Ponieważ funkcja agregująca ignoruje wartości NULL, musisz policzyć kolumnę z wewnętrznej tabeli (policzyłeś z zewnętrznej tabeli), o której wiadomo, że jest zdefiniowana jako NIE NULL (aby móc rozróżnić NULL w danych i NULL utworzonych przez Outer Join). Najłatwiej jest policzyć kolumnę łączenia:COUNT(u.streetid)
dnoeth
Ponieważ right joini right outer joinsą takie same. Dodałem wyjaśnienie w mojej odpowiedzi, zgodnie z sugestią @ jpmc26.
SqlWorldWide

Odpowiedzi:

18

Powód, dla którego zapytanie nie działało zgodnie z przeznaczeniem:

Łączenie wewnętrzne daje przecięcie 2 tabel. W twoim przypadku nie było wpisu 5th streetw tabeli użytkowników i dlatego join nie wygenerowało dla niego żadnego wpisu.

Sprzężenie zewnętrzne (prawe lub lewe) da wynik sprzężenia wewnętrznego, a ponadto wszystkie niekwalifikujące się rekordy z lewej lub prawej tabeli, w zależności od rodzaju (lewego lub prawego) sprzężenia zewnętrznego.

W tym przypadku umieściłem Street po lewej stronie sprzężenia i użyłem lewego sprzężenia zewnętrznego, tak jak chciałeś, aby wszystkie ulice (nawet liczba wynosi zero) w zestawie wyników.

Zmień na to wybrane zapytanie.

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

Wynik wprowadź opis zdjęcia tutaj

SqlWorldWide
źródło
2
Dla mnie zmiana z count (*) na count (customer.id) - podobnie jak pokazano powyżej - miała decydującą różnicę. Dzięki :)
Zeek
9

To jeden z możliwych sposobów.

select s.name as streets,
       (select count(*)
        from   users
        where  StreetID = s.id) cnt
from   streets s;
McNets
źródło
7

Czyszczenie kodu do pracy z instancją uwzględniającą wielkość liter ...

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 );

Gdy używasz COUNTnazwy kolumny, zlicza ona NOT NULLwartości.

Używam RIGHT JOINtutaj, by uspokoić Joe Obbisha.

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

Wyniki:

street      count
1st street  2
2nd street  5
3rd street  2
4th street  1
5th street  0
Erik Darling
źródło
0
  1. Uzyskaj liczbę według identyfikatora ulicy
  2. połącz identyfikator ulicy z identyfikatorem z ulic
  3. Użyj Coalsesce jako wartości zerowej

Oto krótkie zapytanie:

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
rakesh
źródło
To znaczy z lewym złączeniem
rakesh