SQL Count, and distinct count(*) by grouping two columns [duplicate] - sql

This question already has answers here:
Selecting COUNT(*) with DISTINCT
(7 answers)
Closed 2 years ago.
I have a table with 2 fields: where someid2 is unique filed
GID Name Some_ID1 Some_ID_2 (unique)
-- ------- ------- -------
1 A A1 K1
1 A A1 K2
1 A A1 K3
1 A A2 K4
2 B B1 K4
3 C C1 K5
3 C C2 K6
3 C C3 K7
3 C C4 K8
I want to group them by name and Gid, with 'count' of two columns
GID Name Count(Some_ID1) Count(Some_ID_2)
-- ------- ------- -------
1 A 2 4
2 B 1 1
3 C 4 4
what i hve tried is grouped the column gid and name but i cant figure out to get count of some_id1
SELECT
gid, name
count( Some_id1) as Some_id1_count , -- need to fix count here
count( Some_id2) as Some_id2_count
FROM table_a
GROUP BY gid, name

I think you just want count(distinct):
select gid, name, count(distinct some_id1) cnt1, count(*) cnt2
from table_a
group by gid, name

Related

how to execute query for each row result of another query

I have 2 tables , one stores IDs and another logs for each ID , i would like to get sum of log for each ID and ID number from these 2 tables
A B
------- -------------
ID ID_C LOG
1 1 15
2 1 30
3 4 44
4 2 14
5 3 88
3 10
2 10
for getting sum query is
SELECT SUM(LOG) FROM B WHERE ID_C ='2' ;
notice ID and ID_C are same but name is different in tables
and for getting all ids available query is
SELECT ID FROM A ;
I would like to get the following table result
result
--------------------
ID SUM
1 45
4 44
2 24
3 98
I tried
SELECT SUM(LOG) FROM B WHERE ID_C in (SELECT ID FROM A ) ;
but it result in sum of all IDs
It looks like you just need a join aggregation here:
SELECT a.ID, SUM(b.LOG) AS SUM
FROM A a
INNER JOIN B b
ON b.ID_C = a.ID
GROUP BY a.ID
ORDER BY a.ID;
Note that the inner join will also remove ID values from the A table which no entries whatsoever in the B table, which seems to be the behavior you want.
you should use inner join and GROUP BY:
SELECT A.ID as ID, SUM(LOG) AS SumLOG
FROM A inner join B ON A.ID = B.ID_C
GROUP BY A.ID
if you needed can use where for ID filter.

How to calculate rank with group by in sql?

Suppose if I have table1 as following
Category Brand Value
A A1 4
B B1 7
C C1 8
A A2 3
B B2 4
C C2 6
A A3 9
B B3 10
C C3 1
A A4 5
Now if I want to calculate rank for each brand but grouped by category how do I go about it?
Something like
Select rank() (over value)
from table
group by category
Expected output is this:
Category Brand Value Rank
A A3 9 1
A A4 5 2
A A1 4 3
A A2 3 4
B B3 10 1
B B1 7 2
B B2 4 3
C C1 8 1
C C2 6 2
C C3 1 3
Maybe you are looking for something like this.
See this official documentation on DENSE_RANK for more details
select brand, category, dense_rank() over(partition by category order by value desc) as dr
from table
You may add a PARTITION BY clause to your RANK() call, specifying the category as the partition.
SELECT RANK() OVER (PARTITION BY category ORDER BY value) rnk
FROM yourTable
ORDER BY category, rnk;

Insert rows for records that exists with a distinct id

I'd like to insert a row for each distinct id that exists in my table. What is the best and efficient practice to add these rows for each distinct id?
ID Name Count
-- ---- ---
A1 ABC 4
A1 BCD 2
B1 KLM 1
C2 STU 3
C2 BCD 1
C2 DEF 5
EXPECTED RESULT AFTER INSERT
ID Name Count
-- ---- ---
A1 ABC 4
A1 BCD 2
A1 EXISTS 1
B1 KLM 7
B1 EXISTS 1
C2 STU 3
C2 BCD 4
C2 DEF 5
C2 EXISTS 1
Use union all:
select id, name, count
from t
union all
select distinct id, 'EXISTS', 1
from t;
An insert is even simpler:
insert into t (id, name, count)
select distinct id, 'EXISTS', 1
from t;

select rows from main table based on highest date in child table between a date range

Sorry for the confusing title.
I've this table:
ApplicantID Applicant Name
-------------------------------
1 Sandeep
2 Thomas
3 Philip
4 Jerin
ALong with this child table which is connected with the above table:
DetailsID ApplicantID CourseName Dt
---------------------------------------------------------------------
1 1 C1 10/5/2014
2 1 C2 10/18/2014
3 1 c3 7/3/2014
4 2 C1 3/2/2014
5 2 C2 10/18/2014
6 2 c3 1/1/2014
7 3 C1 1/5/2014
8 3 C2 4/18/2014
9 3 c3 2/23/2014
10 4 C1 3/15/2014
11 4 C2 2/20/2014
12 4 C2 2/20/2014
I want to get applicantsID, for example, when I specify a date range from
4/20/2014 to 3/5/2014 I should have:
ApplicantID Applicant Name
-------------------------------
3 Philip
4 Jerin
That means the applicants from the main table that must be in the second table and also the highest date of the second table must fall in the specified date range. Hope the scenario is clear.
you can use window analytic function row_number to get applicant with maximum date in the given time range.
select T1.[ApplicantID], [Applicant Name]
from Table1 T1
join ( select [ApplicantID],
ROW_NUMBER() over ( partition by [ApplicantID] order by Dt desc) as rn
from Table2
where Dt BETWEEN '3/5/2014' AND '4/20/2014'
) T
on T1.[ApplicantID] = T.[ApplicantID]
and T.rn =1
You will need to pull the MAX per ApplicantId with a GROUP BY in a sub-query, then JOIN to that result. This should work for you:
Select A.ApplicantId, A.[Applicant Name]
From ApplicantTableName A
Join
(
Select D.ApplicantId, Max(D.Dt) DT
From DetailsTableName D
Group By D.ApplicantId
) B On A.ApplicantId = B.ApplicantId
Where B.DT Between '03/05/2014' And '04/20/2014'

Taking Sample in SQL Query

I'm working on a problem which is something like this :
I have a table with many columns but major are DepartmentId and EmployeeIds
Employee Ids Department Ids
------------------------------
A 1
B 1
C 1
D 1
AA 2
BB 2
CC 2
A1 3
B1 3
C1 3
D1 3
I want to write a SQL query such that I take out 2 sample EmployeeIds for each DepartmentID.
like
Employee Id Dept Ids
B 1
C 1
AA 2
CC 2
D1 3
A1 3
Currently I am writing the query,
select
EmployeeId, DeptIds, count(*)
from
table_name
group by 1,2
sample 2
but it gives me total two rows.
Any help?
If the number of departments i know and small you could do a stratified sampling:
select *
from table_name
sample
when DeptIds = 1 then 2
when DeptIds = 2 then 2
when DeptIds = 3 then 2
end
Otherwise a combination of RANDOM and ROW_NUMBER:
select *
from
(
sel EmployeeId, DeptIds, random(1,10000000) as rand
from table_name
) as dt
qualify
row_number()
over (partition by DeptIds
order by rand) <= 2