カウントがゼロのグループを取得するにはどうすればよいですか?


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 joinright outer join同じものです。@ jpmc26の提案に従って、回答に説明を追加しました。
SqlWorldWide

回答:


17

クエリが意図したとおりに機能しなかった理由:

内部結合は、2つのテーブルの共通部分を提供します。あなたの場合、5th streetusersテーブルにのエントリがありませんでした。そのため、joinはそのエントリを生成しませんでした。

外部結合(右または左)は、内部結合の結果に加えて、外部結合のタイプ(左または右)に応じて、左または右のテーブルのすべての非修飾レコードを提供します。

この場合、結合の左側に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
私にとって、count(*)からcount(customer.id)への変更-上記と同様に-は重要な違いを作りました。ありがとう:)
Zeek

9

これは可能な方法の1つです。

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ここで、Joe Obbishをなだめるためにhereを使用しています。

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. ストリートIDでカウントを取得します
  2. ストリートIDとストリートIDを結合する
  3. null値が発生するため、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

それは左の参加です
rakesh
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.