SQL find total count of each type in a column - sql

I'm learning SQL and am stumped on what should be a simple query. I have a table with the following pattern:
Id | Type
------------
1 | Red
2 | Blue
3 | Blue
4 | Red
..
I would like to write a query to return a table that counts the total number of instances of each type and returns a table with the following pattern, for example, if 'Blue' occurs in 12 rows, and 'Red' occurs in 16 rows in the table above, the result would be:
Blue | Red
-----------
12 | 16

You could do it this way:
SELECT Type, COUNT(*) FROM TABLE GROUP BY Type
If you'd like to see the Types in separate columns, you could do this:
SELECT SUM(CASE WHEN Type = 'Blue' THEN 1 ELSE 0 END) AS Blue, SUM(CASE WHEN Type = 'Red' THEN 1 ELSE 0 END) AS Red FROM TABLE

I suggest using count over partition by. Here's a code I wrote to help my company check for duplicate Technician EmployeeID's and Pincodes, including count and YES/NO columns to allow filtering in excel so they can see what corrections need to be made:
select
t.TechnicianId, t.TechnicianName, t.Pincode, t.EmployeeID
, [Pincode Count] = count(t.Pincode) over (partition by t.Pincode)
, [Duplicate Pincode?] = case count(t.Pincode) over (partition by t.Pincode) when 1 then 'NO' else 'YES' end
, [EmployeeID Count] = count(t.EmployeeID) over (partition by t.EmployeeID)
, [Duplicate EmployeeID?] = case count(t.EmployeeID) over (partition by t.EmployeeID) when 1 then 'NO' else 'YES' end
from Technicians t
group by t.TechnicianId, t.TechnicianName, t.Pincode, t.EmployeeID
order by 4

Related

SQL query inside another query?

I have this table:
total
user
wallet
storagesummary
chain
40
user1
wallet1
2
1
30
user1
wallet1
4
1
8
user1
wallet2
1
1
2
user2
wallet3
3
1
41
user2
wallet3
4
3
And this is what I'm trying to accomplish:
Type1, Type2, n... columns are a combination of storagesummary and chain
Just for the sake of example: if storagesummary == 2 and chain == 1, then it's gonna be Type1.
I tried something like this, but I don't think it's the best approach and I dunno what to do with the user/wallet columns:
SELECT (SELECT total from MyTable where storagesummary = 2 and chain == 1) as Total Type1 Count,
(SELECT total from MyTable where storagesummary = 4 and chain == 1) as Total Type2 Count,
.......
I cant' figure out how to achieve this.
This could use a bit of conditional aggregation to pivot that.
SELECT
CONCAT(t.user, ' / ', t.wallet) AS "User Wallet Address"
, SUM(CASE
WHEN t.storagesummary = 2 AND t.chain = 1
THEN t.total
ELSE 0
END) AS "Total Type1"
, SUM(CASE
WHEN t.storagesummary = 4 AND t.chain = 3
THEN t.total
WHEN t.storagesummary = 1 AND t.chain = 1
THEN t.total
ELSE 0
END) AS "Total Type2"
, SUM(CASE
WHEN t.storagesummary IN(2,5) AND t.chain >= 2
THEN t.total
ELSE 0
END) AS "Total Type3"
FROM MyTable t
GROUP BY t.user, t.wallet
ORDER BY t.user, t.wallet
Not sure if you need SUM or MAX though.
And the logic in the CASE's will needs corrections.
But if you get the concept, then you'll understand what to change.
I think what you are missing is matching internal column names with outer select, for example:
select action_id, next_action_id from ( select action_id, lead(action_id) over (order by action_id) next_action_id from action) where action_id <> next_action_id-1;
that's for oracle db, but normal SQL can fit without next/lead thing.

How i want make 3 rows of the same primary key into 1 row by checking and choose its value using case

For example here, from this table
key | status
1001 | A
1001 | D
1001 | C
the hierarchy will be C>D>A
If the the stats contain C as the value, the person status will become C in one row. It will be like this:
key | status
1001 | C
it will ignore D and A because it has value C. If it doesn't has C,then it will check for D first before A.
So, how can i do that? I dont how to make the 3 row into 1. I tried using
''' CASE WHEN STATUS IN('C')THEN 'C'
ELSE WHEN STATUS IN('D') THEN 'D'
ELSE WHEN STATUS IN('A') THEN 'A'
END AS STATUS '''
But it give error and still can't make the row into 1
You can try the below -
select key, status
from tablname
order by case when status='C' then 1 when status='D' then 2 when status='A' then 3 else 99 end
FETCH FIRST 1 ROW
You can use analytical function row_number as follows:
Select * from
(Select t.*,
Row_number() over (partition by key order by case when status = 'C' then 1
when status = 'D' then 2
when status = 'A' then 3 end) as rn
From your_table)
Where rn = 1;

Joining two rows into one rows (different column) in oracle

I have table with values like this
ID |Name |Balance |Type |ProductName
1 Abdol 10000 1 RAID100
2 HIVE 5000000 2 RAID100
3 Ade 20000 1 RAID200
4 Koi 30000 1 RAID100
I want to re-arrange the table using select script to:
ProductName | Balance_Type_1 | Balance_Type_2
RAID100 40000 5000000
RAID200 20000 0
I've tried nested case when, but it always create one column with Product-name followed by 0 value besides and repeated.
Thank You
You want aggregation :
select productname,
sum(case when type = 1 then balance else 0 end) as balance_type1,
sum(case when type = 2 then balance else 0 end) as balance_type2
from table t
group by productname;
Run the aggregation query whenever is needed, do not create summary table structure in the database. It will be difficult to manage.
One option would be using pivot provided you database has version 11g+ :
select ProductName ,
sum(nvl(Balance_Type_1,0)) as Balance_Type_1,
sum(nvl(Balance_Type_2,0)) as Balance_Type_2
from t
pivot
(
sum( Balance ) for Type in ( 1 as Balance_Type_1, 2 as Balance_Type_2 )
)
group by ProductName;
Demo

condense results into 1 result under a certain limit

So, I have a result set that has a percentage of the total in 1 column and a name in the other column.
So for example -
Name | Percentage
Jill | 12
Sam | 24
Steve| 2
Jeff | 3
Elvis | 59
I am trying to condense any result thats less than 15% into on row,
so my result would be
Name | Percentage
Everyone else| 17
Sam | 24
Elvis | 59
Thanks!
You can use APPLY :
SELECT tt.Name, SUM([Percentage]) AS [Percentage]
FROM table t CROSS APPLY
( VALUES (CASE WHEN [Percentage] < 15
THEN 'Everyone else'
ELSE Name
END)
) tt(Name)
GROUP BY tt.Name;
Use a case expression in a derived table (the sub-query) to put all less than 15% people together. GROUP BY its result:
select name, sum(Percentage)
from
(
select case when Percentage > 15 then name
else 'Everyone else'
end as name,
Percentage
from tablename
) dt
group by name
For such a simple condition, you can just use CASE expressions:
select (case when percentage < 15 then 'Everyone else'
else name
end) as name,
sum(percentage) as percentage
from t
group by (case when percentage < 15 then 'Everyone else'
else name
end)
order by sum(percentage) asc;

Sql Result two columns

I have the following table:
Full name status
ricardo 1 2
ricardo 2 4
How do I make a select to return like this:
name totalstatus1 totalstatus2 total
ricardo 2 4 6
You did not include the name of the column with the 2 and 4 but you could use something similar to this:
select name,
sum(case when status = 1 then value end) totalStatus1,
sum(case when status = 2 then value end) totalStatus2,
sum(value) Total
from yourtable
group by name;
See SQL Fiddle with Demo