web-dev-qa-db-ja.com

'case when count()= 0'& 'where'を使用した場合の誤った結果

誰かがこのクエリを手伝ってくれるとありがたいです。 case when count()=0whereを使用すると正しい結果が得られないようです


私はSQL Serverを使用しており、「Facebook」のようなシステムのDBを使用しています。

メールアドレス、タグ付けのステータス、過去1か月に投稿された投稿の数を表示するクエリを作成しようとしています。タグ付けのステータスは次のようになります。1〜2の投稿にタグ付けする場合-「少数」を表示3〜5の投稿にタグ付けする場合-「中」を表示5以上の投稿にタグ付けする場合-「多数」を表示タグ付けしない場合-「なし」を表示。

以下は私が書いたクエリです。私が書いたクエリの問題は、WHEREの条件のため、「none」を受信しないことです。

正しい結果を表示するためにクエリを変更するにはどうすればよいですか?

select U.Mail, count(P.ID) as PostCount, 
  case 
    when count(P.ID) = 0 then 'none'
        when count(P.ID) <= 2 then 'few'
        when count(P.ID) <= 5 then 'medium'
    else 'many'
  end PostCountCategory
from Users U 
    left join Tagging T on U.Mail = T.Mail
    left join Post P on T.IDPost = P.ID
where datediff(day,P.DatePosted,getdate()) <= 30 --Because of this condition I would never get 'none'
group by U.Mail, U.Gender

データの例:

必要な入力は、Kelly-'none '、Lilly-'none'、Nelly-'few '、Owen-'none'です。

create table Users
(
Mail nvarchar (20) primary key check(Mail like '_%@_%._%' and (Mail like '%[0-9]%' Or Mail like '%[a-z]%'Or Mail like '%[A-Z]%')),
Password nvarchar (8) check (Password like '%[0-9]%' and Password like '%[az]%' and len(password) <= 8) not null,
FirstName nvarchar (20) not null,
LastName nvarchar (20) not null,
BirthDate date check (datediff(year,BirthDate,getdate())>=18) not null,
JoinDate date check (JoinDate<=getdate()) not null,
Gender nchar(1) check(Gender = 'F' or Gender = 'M' or Gender = 'O'),
NickName nvarchar(20),
Photo nvarchar(20),
Phone bigint check (Phone like '%[0-9]%' and len(Phone) <= 10) not null
)

INSERT INTO Users
VALUES
('[email protected]','k1000000','Kelly','Ka','1992-05-15','2016-09-04','F','Kelly','Kelly.jpg','546296100'),
('[email protected]','l1101111','Lilly','La','1999-04-03','2012-04-04','F','Lilly','Lilly.jpg','542448300'),
('[email protected]','n130131','Nelly','Na','1994-03-07','2020-04-13','F','Nelly','NellyNa.jpg','541234567');
('[email protected]','o140141','Owen','Oa','1992-02-02','2020-05-13','M','Owen','OwenOa.jpg','541234567');


create table Post
(
ID int identity(1,1) primary key,
Photo nvarchar(20),
Text nvarchar(200),
Location nvarchar(50),
Video int,
DatePosted date check (datediff(month,DatePosted,getdate())<=3) not null,
UserMail nvarchar (20) references Users(Mail) on delete cascade on update
cascade not null
)

INSERT INTO Post
VALUES
('','my name is nellu','','','2020-05-08','[email protected]'),
('','hii','','','2020-02-19','[email protected]');


create table Tagging
(
Mail nvarchar (20) references Users(Mail) not null,
IDPost int references Post(ID) not null,    
TagMail nvarchar(20) references Users (Mail) not null,
primary key (Mail,IDPost);
)

INSERT INTO Tagging
VALUES
('[email protected]','1','[email protected]'),
('[email protected]','1','[email protected]');
2
Shir K

条件を結合部分に移動するだけです:

select U.Mail, count(P.ID) as PostCount, 
  case 
    when count(P.ID) = 0 then 'none'
        when count(P.ID) <= 2 then 'few'
        when count(P.ID) <= 5 then 'medium'
    else 'many'
  end PostCountCategory
from Users U 
    left join Tagging T on U.Mail = T.Mail
    left join Post P on T.IDPost = P.ID AND datediff(day,P.DatePosted,getdate()) <= 30
group by U.Mail, U.Gender

また、元の状態では、SQL Serverがインデックスシークを使用できません。このように書き直す方が良いでしょう:

P.DatePosted >= dateadd(day, -30, cast(getdate() as date))
4
Nikita


最初に、PostテーブルとTaggingテーブルを組み合わせます。ここで、次のようにカウントします。

 SELECT T.Mail,COUNT(P.ID) as myCount
 FROM Post as P
    INNER JOIN Tagging as T 
        ON T.IDPost = P.ID
 WHERE datediff(day,P.DatePosted,getdate()) <= 30
 GROUP BY T.Mail

最後に、Usersテーブルに再度参加させます(メールを送信する場合、Group Byは不要です。一意です)。

select U.Mail, p.myCount as PostCount, 
  case 
    when p.myCount = 0 then 'none'
    when p.myCount <= 2 then 'few'
    when p.myCount <= 5 then 'medium'
    when p.myCount > 5 then 'many'
  else 'N/A'
  end PostCountCategory
from Users U 
    --left join Tagging T on U.Mail = T.Mail
    left join 
    (
     SELECT T.Mail,COUNT(P.ID) as myCount
     FROM Post as P
        INNER JOIN Tagging as T 
            ON T.IDPost = P.ID
     WHERE datediff(day,P.DatePosted,getdate()) <= 30
     GROUP BY T.Mail
     )as p 
        ON P.Mail = U.Mail
--where datediff(day,P.DatePosted,getdate()) <= 30 --Because of this condition I would never get 'none'
--group by U.Mail, U.Gender

dbfiddle ここ

2
Sabin Bio