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

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;

Related

Create view with multiple case without fonction

Hello I have to make a view with oracle plsql but I dont know how can I done this wihtout create function:
I got this query
Hello I want to create view who use a query :
select unique tv.id , tv.homeid
case
when ht.hometype = 'A7DF56ZEF' then 0 --HOUSE
when ht.hometype = 'A7DF45ZEF' then 1 -- SMALLHOUSE
end as housetype ,
case
when tv.isfourk is null then 0
when tv.isfourk is not null then 1
end as isfourk
from hometable ht
join tvtable tv on ht.idtv = tv.id
where tv.homeid = 'KLL5FD5Z6'
This query return me result like this
tv.id tv.homeid housetype isfourk
A7844SD KLL5FD5Z6 1 0
A7944SD KLL5FD5Z6 1 0
A8044SD KLL5FD5Z6 1 0
I want to create a view using this query result. this query will be into the view.
The view will have only one row by tv.homeid , like this
Execpted result of the view:
TV.homeid STATE
KLL5FD5Z6 (0 or 1 or 2 or 3 or 4 or 5)
STATE case condition
IF ALL ROWS HAVE isfourk = 1 THEN 1
ELSE IF ALL ROWS WHERE housetype = 1 HAVE isfourk = 1 THEN 2
ELSE IF ONE OF THESE ROWS HAVE isfourk = 0 THEN 3
ELSE IF ONE OF THESE ROWS WHERE housetype = 1 HAVE isfourk = 0 THEN 4
ELSE 5
END as STATE
If you can help me please.
Thanks
I have summarized the query as below after clarifications. I have used your query as base and on top of that applied the case logic to build the view.
One hint , use DISTINCT instead of UNIQUE
CREATE OR REPLACE VIEW give_a_view_name
AS
SELECT homeid
, CASE
WHEN MAX(isfourk) = 1 THEN 1 --IF ALL ROWS HAVE isfourk = 1
WHEN MAX(isfourk) = 1 AND MAX(housetype) = 1 THEN 2 --IF ALL ROWS WHERE housetype = 1 HAVE isfourk = 1 THEN 2
WHEN MIN(isfourk) = 0 THEN 3 --IF ONE OF THESE ROWS HAVE isfourk = 0 THEN 3
WHEN MAX(housetype) = 1 AND MIN(isfourk) = 0 THEN 4 --IF ONE OF THESE ROWS WHERE housetype = 1 HAVE isfourk = 0 THEN 4
ELSE 5 --ELSE 5
END AS state
FROM (SELECT DISTINCT
tv.id
,tv.homeid
,CASE
WHEN ht.hometype = 'A7DF56ZEF' THEN 0 --HOUSE
WHEN ht.hometype = 'A7DF45ZEF' THEN 1 --SMALLHOUSE
END AS housetype
,CASE
WHEN tv.isfourk IS NULL THEN 0
WHEN tv.isfourk IS NOT NULL THEN 1
END AS isfourk
FROM hometable ht
JOIN tvtable tv ON ht.idtv = tv.id
WHERE tv.homeid = 'KLL5FD5Z6')
GROUP BY homeid;
Check and see if it works.

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

sql server count distinct value of a field

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

Convert multiple columns to a single integer with bitwise operation in SQL

I have table with thousands of rows describing say some product. It has multiple columns about the features of the product. For e.g.
productid productname isOnSale HasVeteranDiscount IsTaxExempt Otherdata1 Otherdata2 ...
1 rice 0 1 1 info1 info2
2 camera 1 0 0 info3 info4
Another table
[Productparts]
Partid parentproductid isGeneric CanBeSoldSeperate OtherData1 Otherdata2 ...
Another table:
ProductId ItemsSold Datesold
1 23 4/20/2013
I have an enum that describes productfeature:
[Flags]
public enum ProductFeature : short
{
None = 0,
isOnSale = 0x001,
HasVeteranDiscount = 0x002,
IsTaxExempt = 0x004,
isGeneric = 0x008,
CanBeSoldSeperate = 0x010,
}
For statistical analysis I need to insert the above data from the three tables into one table as a bitwise or'ed integer of all applicable product features with the count of the products that fall into that category along with product sale counts such as:
ProductTrend
ProductFeatures ItemsSold MonthSold
For e.g if a product isonsale and has one or more part which is generic and has one or more part which can be sold seperate then its 25.
And another product hasveterandiscount and has one or more parts that can be sold seperate then its 18 [HasVeteranDiscount | CanBeSoldSeperate = 18]
My table should look like:
ProductTrend
ProductFeatures ItemsSold MonthSold
25 34 April
18 12 May
The most important part here which I need help is how do I combine the data about the product from multiple columns in multiple tables into one single integer column productFeatures with bitwise operations.
SQL Server supports | for bitwise or:
select productid
, productname
, case when isOnSale = 1 then 1 else 0 end |
case when HasVeteranDiscount = 1 then 2 else 0 end |
case when IsTaxExempt = 1 then 4 else 0 end as Flags
from Table1
Example on SQL Fiddle.
try this , sample here
select productid,intheMonthOf,features,sum(itemsold) as TotalSoldItems
from (
select a.productid,Datename(month,datesold) as intheMonthOf, itemsold,
case when a.isonsale =1 then 1 else 0 end |
case when a.hasveterrandiscount =1 then 2 else 0 end |
case when a.istaxexempt =1 then 4 else 0 end |
case when b.isgeneric =1 then 8 else 0 end |
case when b.canbesoldseparate =1 then 10 else 0 end as features
from t1 a
left outer join t2 b on a.productid=b.parentproductid
inner join t3 c on c.porductid=a.productid )main
group by productid,intheMonthOf,features

Counting similar values on same row, different columns

I want to write a query that will count how many times a certain value appears on each row - on the full table I have more columns and I need to count how many times "9" (for example) appears in all the columns,
In this case the answer would be 3:
PlayerName Nation Kills Deaths SoloKills PartyKills
666 1 9 0 9 9
select PlayerName
, sum(case when Nation = 9 then 1 else 0 end +
case when Kills = 9 then 1 else 0 end +
case when Deaths = 9 then 1 else 0 end +
...
) as SumOfNines
from YourTable
group by
PlayerName