Select ID, Count(ID) and Group by Date - sql

I have an article table which has id and date (month/year) columns, first of all I would like to count ids and group them by date, then I would like to see which id belongs to which date group in single query like that:
id date count
-----------------
1 01/2015 2
2 01/2015 2
3 02/2015 1
4 03/2015 4
5 03/2015 4
6 03/2015 4
7 03/2015 4
I have 2 queries
Select Count(id)
from article
group by date
and
Select id
from article
gives results;
count date id date
------------- ----------
2 01/2015 1 01/2015
1 02/2015 2 01/2015
4 03/2015 3 02/2015
I need a single query like
select count(id), id, date
from....
which brings id, count, date columns to use in my C# code.
Can someone help me with this?

SELECT id,
date,
COUNT(*) OVER (PARTITION BY date) AS Count
FROM article
Sql fiddle

Can't quite do that in one query, but you could use a CTE to produce a single result set:
create table #tt (id int null, dt varchar(8))
insert #tt values
(1,'01/2015'),
(2,'01/2015'),
(3,'02/2015'),
(4,'03/2015'),
(5,'03/2015'),
(6,'03/2015'),
(7,'03/2015')
;with cteCount(d, c) AS
(
select dt, count(id) from #tt group by dt
)
select id, dt, c
from #tt a
inner join cteCount cc
on a.dt = cc.d
drop table #tt
results:
id dt c
1 01/2015 2
2 01/2015 2
3 02/2015 1
4 03/2015 4
5 03/2015 4
6 03/2015 4
7 03/2015 4

if not exists(select * from TEST.sys.objects where type=N'U' and name=N'article')
begin
create table article(
[id] int,
[date] date)
end
with this data:
insert into article(id,date) values(1,convert(date,'15/01/2015',103));
insert into article(id,date) values(1,convert(date,'15/02/2015',103));
insert into article(id,date) values(2,convert(date,'15/03/2015',103));
insert into article(id,date) values(2,convert(date,'15/01/2015',103));
insert into article(id,date) values(3,convert(date,'15/02/2015',103));
insert into article(id,date) values(4,convert(date,'15/03/2015',103));
insert into article(id,date) values(5,convert(date,'15/01/2015',103));
insert into article(id,date) values(5,convert(date,'15/02/2015',103));
insert into article(id,date) values(1,convert(date,'15/03/2015',103));
insert into article(id,date) values(2,convert(date,'15/01/2015',103));
insert into article(id,date) values(3,convert(date,'15/02/2015',103));
insert into article(id,date) values(4,convert(date,'15/03/2015',103));
insert into article(id,date) values(5,convert(date,'15/01/2015',103));
insert into article(id,date) values(1,convert(date,'15/02/2015',103));
insert into article(id,date) values(2,convert(date,'15/03/2015',103));
insert into article(id,date) values(3,convert(date,'15/01/2015',103));
insert into article(id,date) values(4,convert(date,'15/03/2015',103));
select id,[date], count(id) [count] from article
group by [date],[id]
the result:
id date count
1 2015-01-15 1
1 2015-02-15 2
1 2015-03-15 1
2 2015-01-15 2
2 2015-03-15 2
3 2015-01-15 1
3 2015-02-15 2
4 2015-03-15 3
5 2015-01-15 2
5 2015-02-15 1

It's not clear how you want to generate the id field in result. if you
want to generate it manually then use RANK() or if you want to get it
from the table id value then you can use max() or min()(depends
upon on your expected result)
Use RANK() Fiddle Demo Here
Try:
create table tt (id int null, dt varchar(8),count int)
insert tt values
(1,'01/2015',2),
(2,'01/2015',2),
(3,'02/2015',1),
(4,'03/2015',4),
(5,'03/2015',4),
(6,'03/2015',4),
(7,'03/2015',4)
Query:
select count(id) as count,dt,RANK()
over(order by count(id)) as id from tt group by dt
EDIT2:
or you just can use MAX() or MIN()
like:
select count(id) as count,dt,Min(id) as id from tt group by dt
or
select count(id) as count,dt,MAX(id) as id from tt group by dt

Related

Getting List of Employees under Head and sub heads

I want to get a list of employees who come under the given Head/Employee.
It should return all sub-heads and their sub-head and employees under him/her.
Following is the list of all Employees with their designations.
EmpID
Name
Designation
HeadEmpID
1
CEO
1
0
2
CountryHead-USA
2
1
3
CountryHead-UK
2
1
4
StateHead-USA-A
3
2
5
StateHead-USA-B
3
2
6
StateHead-UK-C
3
3
7
ZoneHead-A
9
6
8
ZoneHead-B
9
6
9
ZoneHead-C
9
4
10
CityHead-A
12
7
Lets say we ask Who comes under 'CountryHead-UK'?
It should return
EmpID
Name
Designation
Head
3
CountryHead-UK
2
1
6
StateHead-UK-C
3
3
7
ZoneHead-A
9
6
8
ZoneHead-B
9
6
10
CityHead-A
12
7
If we ask who should come under CEO, then it should return everyone (for this sample data)
DROP TABLE IF EXISTS #A
CREATE TABLE #A (EmpID int,Name VARCHAR(MAX), Designation INT, HeadEmpID INT)
INSERT INTO #A VALUES (1,'CEO',1,0)
INSERT INTO #A VALUES (2,'CountryHead-USA',2,1)
INSERT INTO #A VALUES (3,'CountryHead-UK',2,1)
INSERT INTO #A VALUES (4,'StateHead-USA-A',3,2)
INSERT INTO #A VALUES (5,'StateHead-USA-B',3,2)
INSERT INTO #A VALUES (6,'StateHead-UK-C',3,3)
INSERT INTO #A VALUES (7,'ZoneHead-A',9,6)
INSERT INTO #A VALUES (8,'ZoneHead-B',9,6)
INSERT INTO #A VALUES (9,'ZoneHead-C',9,4)
INSERT INTO #A VALUES (10,'CityHead-A',12,7)
SELECT * FROM #A a
Fiddle: https://dbfiddle.uk/YZH65Xvi
Thanks Larnu for a hint.
Follwing worked.
with cte as (
select e.Empid, e.Name, e.Head, b.Name N1, b.Head new_boss
from #a e
left join #a b on b.Empid = e.Head
union all
select c.Empid, c.Name, c.new_boss, e.name, e.head
from cte c
join #a e on e.Empid = c.new_boss
)
select Empid, Name, Head, N1
from cte WHERE n1 = 'CountryHead-UK'
order by Empid, head

Get data as row per row

How get result as:
Get all from table_1 where ORACLE (ID = 10)
ID DAY ID2
---------------
1 1 10
2 2 10
3 3 10
4 4 10
Structure:
Create table table_1 (
id number primary key,
day_1 number,
day_2 number,
day_3 number,
day_4 number,
day_5 number
)
Insert into table_1 (id,day_1,day_2,day_3,day_4,day_5) values (1,10,null,null,null,null);
Insert into table_1 (id,day_1,day_2,day_3,day_4,day_5) values (2,20,10,20,null,null);
Insert into table_1 (id,day_1,day_2,day_3,day_4,day_5) values (3,null,null,10,null,null);
Insert into table_1 (id,day_1,day_2,day_3,day_4,day_5) values (4,null,null,null,10,null);
Insert into table_1 (id,day_1,day_2,day_3,day_4,day_5) values (5,30,null,null,null,null);
--Note
10 - ORACLE
20 - MSSQL
30 - MYSQL
Use UNPIVOT:
SELECT *
FROM table_1
UNPIVOT (
id2 FOR day IN (
day_1 AS 1,
day_2 AS 2,
day_3 AS 3,
day_4 AS 4,
day_5 AS 5
)
)
WHERE id2 = 10;
Which, for your sample data, outputs:
ID
DAY
ID2
1
1
10
2
2
10
3
3
10
4
4
10
db<>fiddle here

how to count the number of last day

I got a data like it :
id date_ type
1 05/03/2020 A
2 07/03/2020 A
3 15/03/2020 A
4 25/03/2020 B
5 24/03/2020 B
6 31/03/2020 C
7 31/03/2020 D
I used the function last_day,
I did it :
select last_day(date_) from table1
But I got it :
31/03/2020 : 7
And I want to have it :
31/03/2020 : 2
thanks !
If you are looking for the count of records having last day of the month in date_ field then:
Schema and insert statements:
create table table1(id int, date_ date, type varchar(10));
insert into table1 values(1, '05-Mar-2020', 'A');
insert into table1 values(2, '07-Mar-2020', 'A');
insert into table1 values(3, '15-Mar-2020', 'A');
insert into table1 values(4, '25-Mar-2020', 'B');
insert into table1 values(5, '24-Mar-2020', 'B');
insert into table1 values(6, '31-Mar-2020', 'C');
insert into table1 values(7, '31-Mar-2020', 'D');
Query:
select date_, count(*)cnt
from table1
where date_ = last_day(date_)
group by date_;
Ouput:
DATE_
CNT
31-MAR-20
2
If you need all the date_ with count no need to use last_day:
Query:
select date_, count(*)cnt
from table1
group by date_
order by date_;
Output:
DATE_
CNT
05-MAR-20
1
07-MAR-20
1
15-MAR-20
1
24-MAR-20
1
25-MAR-20
1
31-MAR-20
2
db<>fiddle here
I think you want aggregation:
select date_, count(*)
from t
where date_ = last_day(date_)
group by date_;
The way I understood it, "last day" isn't the result of the LAST_DAY function, but maximum date value in that table. The result you're after is count of rows whose date is equal to that "maximum" date.
If that's so, then this might be one option: counting rows is easy. ROW_NUMBER analytic function calculates ordinal numbers of each row, sorted by date in descending order which means that it is the 1st row you need.
Something like this:
SQL> select date_, cnt
2 from (select date_,
3 count(*) cnt,
4 row_number() over (order by date_ desc) rn
5 from table1
6 group by date_
7 )
8 where rn = 1;
DATE_ CNT
---------- ----------
31/03/2020 2
SQL>

I need a way to group data based on previous rows

Let me try to explain this again.
This table has a record for each person for each day of the month. There are approx 20 fields in the table. If any of the fields change (other than the date fields), then I want to group those records. So, for example, if days 1, 2, & 3 are the same, then when I read in day 4 and notice that it is changed, I want to group days 1, 2, & 3 together with a begindate of day one, and an enddate of day 3...etc
Rownum ID BegDate EndDate Field1, Field2.... Field20
1 1 6/1/2017 6/1/2017 xxxx xxxx xxxxx
2 1 6/2/2017 6/2/2017 xxxx xxxx xxxxx
3 1 6/3/2017 6/3/2017 xxxx xxxx xxxxx
4 1 6/4/2017 6/4/2017 yyyy yyyy yyyy
5 1 6/5/2017 6/5/2017 yyyy yyyy yyyy
6 1 6/6/2017 6/6/2017 xxxx xxxx xxxxx
7 1 6/7/2017 6/7/2017 xxxx xxxx xxxxx
8 1 6/8/2017 6/8/2017 zzzz zzzz zzzz
....
So in the example data above, I would have a group with rows 1,2,3 then a group with rows 4,5 then a group with rows 6,7 then a group with 8...etc
ID BegDate EndDate Field1 Field2 ...... Field20 Sum
1 6/1/2017 6/3/2017 xxxx xxxx xxxxx 3
1 6/4/2017 6/5/2017 yyyy yyyy yyyy 2
1 6/6/2017 6/7/2017 xxxx xxxx xxxxx 2
1 6/8/2017 6/15/2017 zzzz zzzz zzzz 8
.....
As example. Create table:
create table t
(date_ datetime,
status varchar(1));
And add data
insert into t values ('2017-11-01','A');
insert into t values ('2017-11-02','A');
insert into t values ('2017-11-03','A');
insert into t values ('2017-11-04','B');
insert into t values ('2017-11-05','B');
insert into t values ('2017-11-06','B');
insert into t values ('2017-11-07','C');
insert into t values ('2017-11-08','C');
insert into t values ('2017-11-09','C');
insert into t values ('2017-11-10','C');
insert into t values ('2017-11-11','B');
insert into t values ('2017-11-12','B');
insert into t values ('2017-11-13','B');
insert into t values ('2017-11-14','B');
insert into t values ('2017-11-15','B');
And use this query
select min(date_start),
IFNULL(date_end,now()),
status
from
( select
t1.date_ date_start,
(select min(date_) from t t2 where t2.date_>t1.date_ and t2.status<>t1.status) - interval 1 day as 'date_end',
t1.status status
from t t1
) a
group by date_end,status
order by 1
http://sqlfiddle.com/#!9/96e27/11
You can do this with a difference of row numbers:
select ID, min(BegDate) as Begdate, max(EndDate) as max(EndDate),
Field1, Field2, ...... Field20,
datediff(day, min(BegDate), max(EndDate))
from (select t.*,
row_number() over (partition by id order by begdate) as seqnum,
row_number() over (partition by id, Field1, Field2, . . ., Field20 order by begdate) as seqnum_2
from t
) t
group by id, (seqnum - seqnum_2), Field1, Field2, . . . Field20 ;
try below query (with 2 extra fields - field1 and field2).
To handle you 20 fields add remaining column whereever you see field1,field2 with field1, field2, field3,......field20
create table #tmp (RowNum int, id int,begdate datetime,EndDate datetime, field1 varchar(10),field2 varchar(10))
insert into #tmp values(1,1,'2017-06-01','2017-06-01','xxxxx','xxxxx')
insert into #tmp values(2,1,'2017-06-02','2017-06-02','xxxxx','xxxxx')
insert into #tmp values(3,1,'2017-06-03','2017-06-03','xxxxx','xxxxx')
insert into #tmp values(4,1,'2017-06-04','2017-06-04','yyyyy','yyyyy')
insert into #tmp values(5,1,'2017-06-05','2017-06-05','yyyyy','yyyyy')
insert into #tmp values(6,1,'2017-06-06','2017-06-06','xxxxx','xxxxx')
insert into #tmp values(7,1,'2017-06-07','2017-06-07','xxxxx','xxxxx')
insert into #tmp values(8,1,'2017-06-08','2017-06-08','zzzzz','zzzzz')
insert into #tmp values(9,1,'2017-06-09','2017-06-09','zzzzz','zzzzz')
insert into #tmp values(10,1,'2017-06-10','2017-06-10','zzzzz','zzzzz')
insert into #tmp values(11,2,'2017-06-04','2017-06-04','yyyyy','yyyyy')
insert into #tmp values(12,2,'2017-06-05','2017-06-05','yyyyy','yyyyy')
insert into #tmp values(13,2,'2017-06-06','2017-06-06','xxxxx','xxxxx')
insert into #tmp values(14,2,'2017-06-07','2017-06-07','xxxxx','xxxxx')
insert into #tmp values(15,1,'2017-06-11','2017-06-11','xxxxx','xxxxx')
insert into #tmp values(16,1,'2017-06-12','2017-06-12','xxxxx','xxxxx')
insert into #tmp values(17,1,'2017-06-13','2017-06-13','zzzzz','xxxxx')
insert into #tmp values(18,1,'2017-06-14','2017-06-14','zzzzz','xxxxx')
insert into #tmp values(19,1,'2017-06-15','2017-06-15','yyyyy','xxxxx')
insert into #tmp values(20,1,'2017-06-16','2017-06-16','zzzzz','xxxxx')
select ID, min(BegDate) as Begdate, max(EndDate) as EndDate,
Field1,Field2, /*Add all other fields here*/
datediff(day, min(BegDate), max(EndDate))+1 As [Sum]
from(
select *,
row_number() over (partition by id order by begdate) as seqnum,
row_number() over (partition by id, Field1,field2 /*Add all other fields here*/ order by begdate) as seqnum_2
from #tmp
) t
group by id, (seqnum - seqnum_2), Field1,Field2 /*Add all other fields here*/
order by ID,Begdate
Drop table #tmp

Delete Duplicate rows from table which have same Id

I have a table Emp which have records like this
Id Name
1 A
2 B
3 C
1 A
1 A
2 B
3 C
Now I want to delete the duplicate rows from the table
I am using this query to select or count number of duplicate records
SELECT NameCol, COUNT(*) as TotalCount FROM TestTable
GROUP BY NameCol HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC
and what query should i write to delete the duplicate rows from table.
if I write this query to delete the duplicate records then it is giving a (0) row Affected result.
`DELETE FROM TestTable
WHERE ID NOT IN ( SELECT MAX(ID) FROM
TestTable
GROUP BY NameCol
)`
For sqlserver 2005+
Testdata:
declare #t table(Id int, Name char(1))
insert #t values
(1,'A'),(2,'B'),(3,'C'),(1,'A'),(1,'A'),(2,'B'),(3,'C')
Delete statement(replace #t with your Emp table)
;with a as
(
select row_number() over (partition by id, name order by id) rn
from #t
)
delete from a where rn > 1
select * from #t
**Q How to Remove duplicate data with help of Rowid**
create table abcd(id number(10),name varchar2(20))
insert into abcd values(1,'abc')
insert into abcd values(2,'pqr')
insert into abcd values(3,'xyz')
insert into abcd values(1,'abc')
insert into abcd values(2,'pqr')
insert into abcd values(3,'xyz')
select * from abcd
id Name
1 abc
2 pqr
3 xyz
1 abc
2 pqr
3 xyz
Delete Duplicate record but keep Distinct Record in table
DELETE
FROM abcd a
WHERE ROWID > (SELECT MIN(ROWID) FROM abcd b
WHERE b.id=a.id
);
run the above query 3 rows delete
select * from abcd
id Name
1 abc
2 pqr
3 xyz