sql query group by count - sql

Hello I have a simple table like this:
name date
n1 d1
n1 d1
n2 d1
n3 d1
n1 d2
n2 d2
n2 d2
n1 d3
n1 d3
n1 d3
n4 d3
Where n# is some name and d# is some date. I need the following result:
name date number
n1 d1 2
n2 d1 1
n3 d1 1
n1 d2 1
n2 d2 2
n1 d3 3
n4 d3 1
What I'm doing is for each date, I count the number of times n# appears. Then I display for each name and date the number.
How can I do this on SQL? thank you

It's just a simple usage of group by
select name, date, count(*)
from table1
group by name, date

Group on the name and date:
select
name, date, count(*) as number
from
SomeTable
group by
name, date
order by
name, date

Related

SQL : select 2 consecutive rows with conditions

I have a table event with 3 columns and would like to select two consecutive rows of the same case id with certain criteria (rules) as follows. I have about 5k+ of different case id to select based on the criteria given and below is just example of 2 case id. I have part of code to try, however, got stuck because i dont know how to select both rows if conditions is met.
Rules:
If D1 follows by D3 THEN Select both rows
IfElse D1 follows by D4 THEN Select both rows
IfElse D2 follows by D1 THEN Select both rows
IfElse D2 follows by D3 THEN Select both rows
IfElse D3 follows by D2 THEN Select both rows
IfElse D3 follows by D1 THEN Select both rows
Else Do not select
Table event:
caseID D Timestamp
-----------------------------------
1 D1 T1
1 D2 T2
1 D3 T3
1 D1 T4
1 D3 T5
1 D2 T6
1 D1 T7
1 D2 T8
1 D4 T9
2 D2 T1
2 D1 T2
2 D2 T3
2 D3 T4
2 D1 T5
2 D4 T6
2 D5 T7
Expected output:
caseID D Timestamp
----------------------------------
1 D2 T2
1 D3 T3
1 D1 T4
1 D3 T5
1 D2 T6
1 D1 T7
2 D2 T1
2 D1 T2
2 D2 T3
2 D3 T4
2 D1 T5
2 D4 T6
Code I might try:
SELECT caseID, D, Timestamp
FROM event e1
INNER JOIN event e2 ON e1.caseID = e2.caseID
WHERE
CASE #D
WHEN e1.D = D1 AND e2.D = D3 THEN ?
Here's one option using lead and lag with case:
select caseid, d, timestamp
from (
select *, lead(d) over (partition by caseId order by timestamp) lead,
lag(d) over (partition by caseId order by timestamp) lag
from event
) t
where 1 = case
when d = 'D1' and lead in ('D3','D4') then 1
when d = 'D2' and lead in ('D1','D3') then 1
when d = 'D3' and lead in ('D2','D1') then 1
when d = 'D1' and lag in ('D2', 'D3') then 1
when d = 'D2' and lag in ('D3') then 1
when d = 'D3' and lag in ('D2','D1') then 1
when d = 'D4' and lag in ('D1') then 1
else 0
end
order by caseid, timestamp
Online Demo
It could be consolidate, but wanted to be as explicit as possible to define your criteria.
Due to SQL-server 2008 didn't support Lag and Lead you can write a subquery to make it.
SELECT caseID,
D,
Timestamp
FROM (
select *,(
select TOP 1 D
FROM T tt
WHERE t1.caseID = tt.caseID
and t1.Timestamp < tt.Timestamp
ORDER BY tt.Timestamp
) nextD,(
select TOP 1 D
FROM T tt
WHERE t1.caseID = tt.caseID
and t1.Timestamp > tt.Timestamp
ORDER BY tt.Timestamp desc
) pervD
from T t1
) t1
WHERE (CASE WHEN d = 'D1' and nextD in ('D3','D4') OR
d = 'D2' and nextD in ('D1','D3') OR
d = 'D3' and nextD in ('D2','D1') OR
d = 'D1' and pervD in ('D2', 'D3') OR
d = 'D2' and pervD in ('D3') OR
d = 'D3' and pervD in ('D2','D1') OR
d = 'D4' and pervD in ('D1')
THEN D END) IS NOT NULL
sqlfiddle

Get the lowest Score of each distinct Name and distinct Group

Need to get the lowest Score of each distinct Name and distinct Group. Thank you.
Data:
Group Name Score
A N1 1
B N1 5
C N1 3
A N1 4
A N2 2
A N3 6
A N1 8
B N1 7
B N2 9
Result:
A N1 1
B N1 5
C N1 3
A N2 2
A N3 6
B N2 9
select [Group], Name , min( Score)
from my_table
group by [Group], Name

Count coincidences between rows in two tables

I am trying to write a query in SQL Server 2014 that counts the number of coincidences (but just when those coincidences are more than 1) between the rows in two tables, into a new column. The structure is like this:
table_a:
================
c1 | c2 | c3 | c4
11 | 30 | 70 | 90
20 | 80 | 95 | 99
15 | 39 | 40 | 41
...
table_b:
================
n1 | n2 | n3 | n4
30 | 65 | 90 | 95
20 | 80 | 90 | 99
15 | 80 | 95 | 99
...
And I want to add a column in a query after the columns in table_a like this:
query:
================
c1 | c2 | c3 | c4 | c5
11 | 30 | 70 | 90 | 2
20 | 80 | 95 | 99 | 6
15 | 39 | 40 | 41 | 0
...
In other words, for each row in table_a check how many numbers match each row in table_b , afterwards sum all results greater than 1 and paste next to the row in table_a.
I have the following code but I get wrong output:
SELECT TOP (100) PERCENT dbo.table_a.c1, dbo.table_a.c2,
dbo.table_a.c3, dbo.table_a.c4, dbo.table_a.c5, dbo.table_a.c6,
COUNT('c1 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c2 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c3 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c4 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c5 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c6 = n1 or n2 or n3 or n4 or n5 or n6') AS c5
FROM dbo.table_a CROSS JOIN dbo.[table_b]
GROUP BY dbo.table_a.c1, dbo.table_a.c2, dbo.table_a.c3, dbo.table_a.c4,
dbo.table_a.c5, dbo.table_a.c6
HAVING (COUNT('c1 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c2 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c3 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c4 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c5 = n1 or n2 or n3 or n4 or n5 or n6')
+ COUNT('c6 = n1 or n2 or n3 or n4 or n5 or n6') > 1)
ORDER BY c5 DESC
Any help would be appreciated, thx!
;with cte(n) as(
select n1 from table_b union all
select n2 from table_b union all
select n3 from table_b union all
select n4 from table_b
)
,counted(n, c) as(
select n, c = count(n) from cte group by n
)
select
a.*, b.cc
from table_a a
cross apply(
select cc = sum(case when c > 1 then c else 0 end)
from counted
where
n = a.c1
or n = a.c2
or n = a.c3
or n = a.c4
)b

sql query to find what is not in group three

i have one SQL Table in which some dummy data.
i want that dummy data and update that row with column type
my table tbl
ID D1 M1 C1 QTY TYPE
1 D1 M1 C1 1 Y
2 D1 M2 C1 2 Y
3 D1 M3 C1 3 Y
4 D1 M1 C1 1 Y
5 D2 M1 C1 1 Y
6 D2 M2 C1 2 Y
7 D2 M3 C2 3 Y
8 D2 M1 C1 1 Y
9 D2 M2 C1 2 Y
10 D3 M1 C1 1 Y
11 D3 M2 C1 2 Y
12 D3 M3 C1 3 Y
13 D3 M1 C1 1 Y
14 D3 M2 C1 2 Y
15 D3 M3 C1 3 Y
16 D3 M1 C2 1 Y
grouping on Column D1 and M1
I have a N no. of records, now I have to identify group of 3 record and if any record remain then it should be set as "No" else "yes"
Ex:
condition 1: If I have 4 records, then make a group of 3-3 records so remain last 1 record should be set an "no".
condition 2: If I have 5 records, then make a group of 3-3 records so remain last 2 records will be set as "No"
Condition 3: if I have 7 records, then make a group of 3-3 records so remain last 1 record will be set as "No"
my expected answer is as below
ID D1 M1 C1 QTY TYPE
1 D1 M1 C1 1 YES
2 D1 M2 C1 2 YES
3 D1 M3 C1 3 YES
4 D1 M1 C1 1 NO
5 D2 M1 C1 1 YES
6 D2 M2 C1 2 YES
7 D2 M3 C2 3 YES
8 D2 M1 C1 1 NO
9 D2 M2 C1 2 NO
10 D3 M1 C1 1 YES
11 D3 M2 C1 2 YES
12 D3 M3 C1 3 YES
13 D3 M1 C1 1 YES
14 D3 M2 C1 2 YES
15 D3 M3 C1 3 YES
16 D3 M1 C2 1 NO
SQLFIDDLE
Please tell me solution.
Is this what you are looking for?
with toupdate as (
select t.*, row_number() over (partition by d1 order by id) as seqnum,
count(*) over (partition by d1) as cnt
from tbl t
)
update toupdate
set type = (case when seqnum <= 3*(cnt /3) then 'yes' else 'no' end);
You can also run similar logic as a select:
select t.*, (case when seqnum <= 3*(cnt /3) then 'yes' else 'no' end)
from (
select t.*, row_number() over (partition by d1 order by id) as seqnum,
count(*) over (partition by d1) as cnt
from tbl t
) t;

SQL Query without duplicates

I have 3 tables like this:
Names:
ID(K) Name
--------------
1 n1
2 n2
Jobs:
ID Job
------------
1 j1
1 j2
Phones:
ID Phone
--------------
1 p1
1 p2
1 p3
1 p4
I'm doing a SELECT with LEFT OUTER JOIN:
SELECT Names.Name, Jobs.Job, Phones.Phone
FROM
Names LEFT OUTER JOIN Jobs ON Jobs.ID = Names.ID
LEFT OUTER JOIN Phones ON Phones.ID = Names.ID
and returns:
n1 j1 p1
n1 j1 p2
n1 j1 p3
n1 j1 p4
n1 j2 p1
n1 j2 p2
n1 j2 p3
n1 j2 p4
n2 null null
but i need this results:
n1 j1 p1
n1 j2 p2
n1 null p3
n1 null p4
n2 null null
what's the solution?
You're not specifying which RDBMS, but this query works on at least SQL Server, PostgreSQL and Oracle. There may be a smarter analytic function to do this, but it escapes me at the moment.
WITH pjobs AS (
SELECT id, job,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY job) rn FROM jobs
), pphones AS (
SELECT id, phone,
ROW_NUMBER() OVER(PARTITION BY id ORDER BY phone) rn FROM phones
)
SELECT name, job, phone
FROM pjobs FULL JOIN pphones ON pjobs.rn = pphones.rn AND pjobs.id = pphones.id
RIGHT JOIN names ON names.id = pjobs.id OR names.id = pphones.id
An SQLfiddle to test with.