SQL count of values from different columns - sql

I've got a Dog table. Each dog has Breed and can have 0 to 2 photos. I need to recieve count of photos of all dogs for each breed: table with BreedId and matching PhotosCount. So result table should be:
BreedID|PhotosCount
-------------------
1 |3
-------------------
2 |1
-------------------

This should do the trick:
SELECT BreedID AS B, COUNT(Photo1) + COUNT(Photo2) AS C
FROM Dog
GROUP BY BreedID
COUNT aggregate function simply doesn't take into consideration NULL values. If, for a specific BreedID, all values of either Photo1 or Photo2 are NULL, then COUNT returns 0.

This should work in single scan:
SELECT
BreedID,
SUM(CASE WHEN Photo1 IS NOT NULL THEN 1 ELSE 0 END)
+ SUM(CASE WHEN Photo2 IS NOT NULL THEN 1 ELSE 0 END) [Count]
FROM Table
GROUP BY BreedID

Use Group By and SUM Of Photo1 and Photo2:
Note: If you wants the output for each dog you have to include DogId in group clause.
;WITH T AS
(
SELECT
BreedId,
SUM (CASE ISNULL(Photo1,0) WHEN 1 THEN 1 ELSE 0 END) AS Photo1,
SUM (CASE ISNULL(Photo2,0) WHEN 1 THEN 1 ELSE 0 END) AS Photo2
FROM TableName
Group By BreedId
)
SELECT
BreedId,
SUM(Photo1+Photo2) AS TotalPhoto
FROM T
Or Simply
SELECT
BreedId,
SUM (CASE ISNULL(Photo1,0) WHEN 1 THEN 1 ELSE 0 END + CASE ISNULL(Photo2,0) WHEN 1 THEN 1 ELSE 0 END) AS TotalPhoto
FROM TableName
Group By BreedId

SELECT BreedID AS Breed, COUNT(Photo1) + COUNT(Photo2) AS #ofPhotos
FROM Dog
GROUP BY BreedID;

Related

Checking if all values for user_id IS NOT NULL

I have dataset which looks like this:
UserID AccountID CloseDate
1 1000 14/3/2022
1 2000 16/3/2022
2 1000 NULL
2 2000 4/3/2022
2 3000 NULL
And I would like to check if within one user_id all of the close dates are not null. In other words if all accounts within user_id are closed. I was trying using MAX or MIN but it is not working as I expected, because it is simply avoiding NULL values. Is there any other function which can check it? Let's say that my output would be another column which will assign 1 when all CloseDates are not null and else 0.
Sample output:
UserID AccountID CloseDate Check
1 1000 14/3/2022 1
1 2000 16/3/2022 1
2 1000 NULL 0
2 2000 4/3/2022 0
2 3000 NULL 0
Use conditional aggregation to explicitly COUNT the rows where the column has the value NULL:
SELECT GroupedColumn,
COUNT(CASE WHEN NullableColumn IS NULL THEN 1 END) AS NullCount
FROM dbo.YourTable
GROUP BY GroupedColumn;
If you want to just have a 1 or 0 just wrap the count in a CASE expression:
CASE COUNT(CASE WHEN NullableColumn IS NULL THEN 1 END) WHEN 0 THEN 1 ELSE 0 END
You can try to use FIRST_VALUE condition window function
SELECT *,
FIRST_VALUE(IIF(CloseDate IS NULL,0,1)) OVER(PARTITION BY UserID ORDER BY CloseDate )
FROM T
sqlfiddle
with dataset as (select 1 as UserId, 1000 as AccountID, '14/3/2022' as CloseDate
union all select 1, 2000, '16/3/2022'
union all select 2, 1000, NULL
union all select 2, 2000, '4/3/2022'
union all select 2, 3000, NULL)
select userid from dataset
group by userid
having sum(case when closedate is null then 1 else 0 end) = 0;
select d.*, iif(chk>0, 0, 1) chk
from d
outer apply (
select UserId, COUNT(*) CHK
from d dd
WHERE d.UserId = dd.UserId
and dd.CloseDate IS NULL
group by UserId
) C
You can also use "exists". e.g. :
select y.UserID, y.AccountID, y.CloseDate,
-- [Check]: returns 0 if there is a row in the table for the
-- UserID where CloseDate is null, else 1
(case when exists(select * from YourTable y2 where y2.UserID = y.UserID
AND y2.CloseDate is null) then 0 else 1 end) as [Check]
from YourTable y

How to find number of nulls in a table SQL

Let's say that I have an employee table. And it has columns like name, salary, and age. If I want to check if there any nulls in the name. I gotta write
SELECT name FROM EMPLOYEE
WHERE name IS NULL;
But what should I do to see the number of nulls each column has?
Probably the simplest method is:
select count(*) - count(name) as num_name_nulls,
count(*) - count(col1) as num_col1_nulls,
. . .
from employee;
However, what I do in this situation is just select the counts:
select count(*), count(name), count(col1), . . .
from employee;
Then I eyeball the result to see if the counts are not equal.
I assume you want to see nulls for a column, you can apply conditional aggregation.
SELECT COUNT(CASE WHEN name is null then 1 end) AS Name_NullCount,
COUNT(CASE WHEN salary is null then 1 end) as salary_nullCount,
COUNT(CASE WHEN age is null then 1 end) as age_nullcount
FROM EMPLOYEE;
You can use below query but it depends on number of columns. It will give number of nulls each row has.
select
((case when column1 is null then 1 else 0 end)
+ (case when column2 is null then 1 else 0 end)
----------------------------------------
----------------------------------------
+(case when columnN is null then 1 else 0 end))
from TableName
For your case
select
((case when name is null then 1 else 0 end)
+(case when salary is null then 1 else 0 end)
+(case when age is null then 1 else 0 end))
from employee
you can find Null values per row from following query
SELECT
(
(CASE WHEN name IS NULL THEN 1 ELSE 0 END)+
...
...
+(CASE WHEN colName IS NULL THEN 1 ELSE 0 END)
) AS sum_of_nulls
FROM EMPLOYEE
WHERE EmpId = 49
where colName is your Db Column Name
select
sum(case
when name is null then 1
when name is not null tehn 0
end) cname,
sum(case
when salary is null then 1
when salary is not null then 0
end) csalary,
...
from employee
limit 1;

SQL: Multiple select that differ by only one condition

I've got a beginner question. My SQL table looks like:
| Date | Type | Manufacturer |
2016/04/01 A X
2016/04/01 B Y
2016/04/02 B X
2016/05/07 A Z
... ... ...
My aim is to count the quantity of "Types" by manufacturers between two dates. I would like to get a result like following:
| Manufacturer | Quantity_TypeA | Quantity_TypeB |
X 1 1
Y 0 1
Z 1 0
My query looks like:
select Manufacturer as Manufacturer,
COUNT(*) as Quantity_TypeA
From MyTable
Where [Type] = 'A' and
Date between '20150101' and '20160930',
COUNT(*) as Quantity_TypeB
From MyTable
Where [Type] = 'B' and
Date between '20150101' and '20160930'
group by Manufacturer Order by Quantity_TypeA DESC
I have also tried to use functions like CASE on the Type and it didn't work. I am missing something but what?
Try this
select Manufacturer as Manufacturer,
SUM(case when [Type] = 'A' then 1 else 0 end) as Quantity_TypeA,
SUM(case when [Type] = 'B' then 1 else 0 end) as Quantity_TypeB
From MyTable
Where
Date between '20150101' and '20160930'
group by Manufacturer
Use case expressions to do conditional counting:
select Manufacturer as Manufacturer,
COUNT(case when [Type] = 'A' then 1 end) as Quantity_TypeA,
COUNT(case when [Type] = 'B' then 1 end) as Quantity_TypeB
from MyTable
where Date between '20150101' and '20160930',
group by Manufacturer
order by Quantity_TypeA DESC
count() does only count non-null values. The case expressions either return 1 or null, i.e. only A's or B's are counted.

Combine multiple rows into 1 row

Say for example I have a table that contains a description of a customer's activities while in a cafe. (Metaphor of the actual table I am working on)
Customer Borrowed Book Ordered Drink Has Company
1 1
1 1
1 Yes
2 1
3 1
3 Yes
4 1 1
4 1
I wish to combine the rows in this way
Customer Borrowed Book Ordered Drink Has Company
1 1 1 Yes
2 1
3 1 Yes
4 1 2
I did self join with coalesce, but it did not give my desired results.
You can do this by group by,
select Customer,sum([borrowed book]), sum([ordered drink]), max([has company])
from customeractivity group by Customer
As per your comment, initial table is a temp table,
Try to make the result as a cte result, then do aggregation on that, like the below query.
; WITH cte_1
AS
( //your query to return the result set)
SELECT customer,sum([borrowed book]) BorrowedBook,
sum([ordered drink]) OrderedDrink,
max([has company]) HasCompany
FROM cte_1
GROUP BY Customer
Use Group By:
DECLARE #tblTest as Table(
Customer INT,
BorrowedBook INT,
OrderedDrink INT,
HasCompany BIt
)
INSERT INTO #tblTest VALUES
(1,1,NULL,NULL)
,(1,NULL,1,NULL)
,(1,NULL,NULL,1)
,(2,NULL,1,NULL)
,(3,NULL,1,NULL)
,(3,NULL,NULL,1)
,(4,1,1,NULL)
,(4,NULL,1,NULL)
SELECT
Customer,
SUM(ISNULL(BorrowedBook,0)) AS BorrowedBook,
SUM(ISNULL(OrderedDrink,0)) AS OrderedDrink,
CASE MIN(CAST(HasCompany AS INT)) WHEN 1 THEN 'YES' ELSE '' END AS HasCompany
FROM #tblTest
GROUP BY Customer
Not sure, why you are getting error with group by.
Your coalesce should be correct. Refer below way.
Select customer
, case when [borrowed] = 0 then NULL else [borrowed] end as [borrowed]
, case when [ordered] = 0 then NULL else [ordered] end as [ordered]
, case when [company] = 1 then 'Yes' end as company
from
(
Select customer,
coalesce(
case when (case when borrowed = '' then null else borrowed end) = 1 then 'borrowed' end,
case when (case when ordered = '' then null else ordered end) = 1 then 'ordered' end,
case when (case when company = '' then null else company end) = 'Yes' then 'company' end
) val
from Table
) main
PIVOT
(
COUNT (val)
FOR val IN ( [borrowed], [ordered], [company] )
) piv
OUTPUT:
customer | borrowed | ordered | company
---------------------------------------
1 1 1 Yes
2 NULL 1 NULL
3 NULL 1 Yes

Count Values from Table for each type

I have the following table
UserId [nvarchar(128)], Rating [varchar(170)] :values will be mostly 1,2,3 but can have exceptions
Rating contains 3 values [1,2, or 3]
I want to get a result something like
UserId Count(1's),Count(2's) Count(3's)
1. 1001 10 8 2
2. 1002 5 10 3
Is it possible in a single query
Do a GROUP BY UserId to count for each user-id. Use CASE to count 1's, 2's and 3's separately:
select UserId,
count(case when Rating = 1 then 1 end) as [Count(1's)],
count(case when Rating = 2 then 1 end) as [Count(2's)],
count(case when Rating = 3 then 1 end) as [Count(3's)]
from tablename
group by UserId
Use a CASE statement in each COUNT and then GROUP BY UserId.
SELECT UserId, COUNT(CASE WHEN value = '1' THEN 1 END) AS [Count(1's)], COUNT(CASE WHEN value = '2' THEN 1 END) AS [Count(2's)], COUNT(CASE WHEN value = '3' THEN 1 END) AS [Count(3's)]
FROM yourtable
GROUP BY UserId
Use PIVOT:
SELECT
UserId,
COALESCE([1],0) [Count(1's)],
COALESCE([2],0) [Count(2's)],
COALESCE([3],0) [Count(3's)]
FROM
ýour_table
PIVOT
(COUNT([Rating])
FOR Rating
in([1],[2],[3])
)AS p
ORDER BY
UserId