sql server count distinct value of a field - sql

I have 2 tables : Contents and Packs
In Content columns are like this:
Id Name IsPerishable IsSpecial IsDanger
----------------------------------------------------------
1 Paper False False False
3 Fruit True False False
5 NewsPaper False True False
6 Radioactive False False True
7 Foods True False False
In Packs columns are like this:
Id From To ContentId
---------------------------------------
1 ABZ ATL 3
2 ANU ATL 5
3 BAQ ATL 7
4 BTS BAQ 6
5 FRL BAQ 5
Now I want a result that groups every 'To' then shows separate value of IsPerishable / IsSpecial / IsDanger
like this:
To Perishable Special Danger
-----------------------------------------------
ATL 2 1 0
BAQ 0 1 1
I try use some query but none of them has worked correctly:
select Name,
case
when IsSpecial = 1 then count(IsSpecial)
when IsPerishable = 1 then count(IsPerishable)
when IsDanger = 1 then count(IsDanger)
end as 'Content'
from Contents
group by IsSpecial , IsPerishable , IsDanger
select To,count(DISTINCt Id) as 'Count'
FROM Packs
GROUP BY To

try this
Select To,
(Select count(*) from Content c where c.Id= p.Id and c.IsSpecial=1) as Special,
(Select count(*) from Content c where c.Id= p.Id and c.Isperishable=1) as Perishable,
(Select count(*) from Content c where c.Id= p.Id and c.Isperishable=1) as Danger
from
pack p
group by To

SELECT P.To, SUM(Perishable), SUM(Special),SUM(Danger) FROM
(
SELECT Id,
CASE IsPerishable WHEN true THEN 1 ELSE 0 END AS Perishable,
CASE IsSpecial WHEN true then 1 ELSE 0 END AS Special,
CASE IsDanger WHEN true then 1 ELSE 0 END AS Danger
FROM Contents
) C
Right Join Packs P
on P.ContentId=C.Id
Group BY P.to

Related

adding sequential number into a column

I have written the code below trying to add a sequential number to a column but I am not getting my desire result.
WHERE as_at_date=(SELECT MAX(as_at_date) FROM my_table)
UNION ALL
SELECT p.customer_id, p.has_referred, (p.row_count) + 1 FROM my_table f
INNER JOIN row_num p ON p.customer_id= f.customer_id and p.row_count = 1)
--, row_num p WHERE p.customer_id = f.customer_id AND p.row_count = 4)
SELECT * FROM row_num;
I supposed to be getting something like this
customer_id
has_referred
row_count
1
true
1
2
false
2
3
true
3
However I am getting
customer_id
has_referred
row_count
1
true
1
2
false
1
3
true
1
Can I please get some help to why this is happening? Thanks in advance.

How to count and group not null elements in SQL Server?

I have a table where each row represents a user and each column represents a service that the customer may have hired. I need to count how many customers hired 1 service, how many hired 2 and so on. It doesn't matter what service you hire. And there is no identifier column.
In Python I was able to do this with
result = services.count(axis = 1).value_counts()
result = pd.DataFrame(result, columns = ['n_clients'])
where 'result' is the csv with the database.
The result, in this case, are like:
n_client
1
928459
2
280235
3
53731
4
16042
Edit: an example of the database to clarify:
product1
product2
product3
product4
True
True
True
True
True
True
True
True
True
True
True
In this case, the result should look like:
n_client
1
4
2
2
3
1
4
0
It looks like you want to just calculate how many products per row, then group by that number
SELECT
v.CountProducts
n_client = COUNT(*)
FROM YourTable
CROSS APPLY (VALUES (
CASE WHEN product1 = 'True' THEN 1 ELSE 0 END +
CASE WHEN product2 = 'True' THEN 1 ELSE 0 END +
CASE WHEN product3 = 'True' THEN 1 ELSE 0 END +
CASE WHEN product4 = 'True' THEN 1 ELSE 0 END
) ) v(CountProducts)
GROUP BY
CountProducts;

SQL To count values of multiple columns

I have a table, with columns like this:
name1,name2,name_thesame,adress1,adress2,adress_thesame,city1,city2,city_thesame
In all columns ending with _thesame, there is a true or false depending if name1 and name2 are the same, same with adress etc etc.
I now need a query that returns a count how many true and false i got for each of the _thesame columns.
Cant wrap my head around how to do this query - any body got some ideas or pointers? Thanks
For a single property you can do:
select name_thesame, count(*)
from table
group by name_thesame
This will give you results like:
true 10
false 15
If you want to have it as a list for multiple columns, you can just union the queries:
select 'Name', name_thesame, count(*)
from table
group by name_thesame
union
select 'Address', adress_thesame, count(*)
from table
group by adress_thesame
getting:
Name true 10
Name false 15
Address true 20
Address false 5
This is another option:
SELECT SUM(CASE WHEN name_thesame = true THEN 1 ELSE 0 END) as nametrue,
SUM(CASE WHEN name_thesame = false THEN 1 ELSE 0 END) as namefalse,
SUM(CASE WHEN adress_thesame = true THEN 1 ELSE 0 END) as adresstrue,
SUM(CASE WHEN adress_thesame = false THEN 1 ELSE 0 END) as adressfalse,
SUM(CASE WHEN city_thesame = true THEN 1 ELSE 0 END) as citytrue,
SUM(CASE WHEN city_thesame = false THEN 1 ELSE 0 END) as cityfalse
FROM yourTable
You can tweak it to deal with NULLs as well if relevant:
...
CASE WHEN name_thesame = false OR name_thesame IS NULL THEN 1 ELSE 0 END
...
or either NVL(), ISNULL(), IFNULL() or COALESCE(), depending on the DBMS you're using (syntax is always the same):
...
CASE WHEN COALESCE(name_thesame, false) = false THEN 1 ELSE 0 END
...
Result:
nametrue | namefalse | adresstrue | adressfalse | citytrue | cityfalse
5 | 7 | 2 | 1 | 10 | 8

Group by clause with count() and where condition in subquery

Table : Class
id Institute_id Name
------------------------------
1 1 MCAL - 1
2 1 MCAL - 2
3 1 BCA - 1
4 1 BCA - 2
Table : Groups
id Class_Id Institute_Id Name Status
--------------------------------------------------
1 1 1 PHP false
2 2 1 JAVA false
3 1 1 ORACLE false
4 2 1 LINUX true
5 2 1 ASP.NET false
6 3 1 OS false
7 4 2 CPP false
Expected Result :
id Name Count(*)
-----------------------------
1 MCAL - 1 2
2 MCAL - 2 2
3 BCA - 1 1
4 BCA - 2 0
Note: count only those records from Groups where Institute_Id = 1 and Status=false
Please try this
Select
c.id,
c.name,
SUM(case when g.class_id is NULL then 0 else 1 end) as count
from class c left join groups g
on c.id=g.class_id
and g.status='false'
and g.Institute_id=1
group by c.id,c.name
order by c.id
fiddle link: http://sqlfiddle.com/#!6/2b992/6
To count properly with outer joins, specify the column name instead of * in COUNT().
SELECT C.id, C.Name, [Count] = COUNT(G.Status)
FROM Class C
LEFT JOIN Groups G ON C.id = G.Class_id AND G.Institute_id = 1 AND G.Status = 'false'
GROUP BY C.id, C.Name
ORDER BY C.id

Value carry forword

I have below SQL Query..
SELECT dbo.O3.[s.no] AS [O3_Sn.NO], dbo.O5.[s.no] AS [O5_Sn.NO], dbo.O3.O3, dbo.O5.O5,
case when dbo.O3.[s.no] > dbo.O5.[s.no] then 'true' else 'false' end as ComparisonColumn
FROM dbo.O3 INNER JOIN
dbo.O5 ON dbo.O3.[s.no] = dbo.O5.[s.no]
When I run I am getting below output..
O3_Sn.NO O5_Sn.NO O3 O5 ComparisonColumn
1 1 10 11 TRUE
2 2 12 13 TRUE
3 3 11 10 FALSE
4 4 13 11 FALSE
5 5 15 16 TRUE
6 6 10 11 TRUE
7 7 12 13 TRUE
I want to remember the value of TRUE / False and should ignore if it is repeated untill i get a reverse case i.e., for TRUE , False.. and FOR False .. TRUE
Below is the out i should get it..
O3_Sn.NO O5_Sn.NO O3 O5 ComparisonColumn New_Case_Carry_value
1 1 10 11 TRUE TRUE
2 2 12 13 TRUE NULL
3 3 11 10 FALSE FALSE
4 4 13 11 FALSE NULL
5 5 15 16 TRUE TRUE
6 6 10 11 TRUE NULL
7 7 12 13 TRUE NULL
You can order your output using row_number() to compare a value with a value of the previous record:
with cIntermediate as (
SELECT dbo.O3.[s.no] AS [O3_Sn.NO], dbo.O5.[s.no] AS [O5_Sn.NO], dbo.O3.O3, dbo.O5.O5,
case when dbo.O3.[s.no] > dbo.O5.[s.no] then 'true' else 'false' end
as ComparisonColumn,
rowno = row_number() over
(order by dbo.O3.[s.no], dbo.O5.[s.no], dbo.O3.O3, dbo.O5.O5)
FROM dbo.O3 INNER JOIN dbo.O5 ON dbo.O3.[s.no] = dbo.O5.[s.no]
)
select i1.*,
case when i1.ComparisonColumn = i2.ComparisonColumn then null
else i1.ComparisonColumn end as NewCaseCarryValue
from cIntermediate i1
left join cIntermediate i2 on i2.rowno=i1.rowno-1
Ok, I will explain the concept to you, and I am sure you will be able to figure it out for yourself.
Your final result you published with all the true and false columns, that needs to become a temporary table, like this, but with some kind of identity column:
SELECT dbo.o3.[s.no] AS [O3_Sn.NO]
,dbo.o5.[s.no] AS [O5_Sn.NO]
,dbo.o3.o3
,dbo.o5.o5
,CASE
WHEN dbo.o3.[s.no] > dbo.o5.[s.no] THEN 'true'
ELSE 'false'
END AS comparisoncolumn
, ROW_NUMBER() OVER(ORDER BY dbo.o3.[s.no]) AS ident_col
INTO #temp
FROM dbo.o3
INNER JOIN dbo.o5
ON dbo.o3.[s.no] = dbo.o5.[s.no]
Then what you need to do is to select from #temp, and self join to #temp in a similar manner as here:
SELECT a.*
, CASE WHEN a.comparisoncolumn = b.comparisoncolumn THEN NULL ELSE a.comparisoncolumn END AS final_comparisoncolumn
FROM #temp a
LEFT JOIN #temp b ON a.ident_col = b.ident_col - 1
Then do a case statement to figure out if you need to print null, or true or false.
Play around with this concept, I am sure you will be able to work it out from here.
You can do an left join on the table itself (SN = SN-1) and compare the ComparisonColumn