Select changed records - sql

I have what I would have thought was a common problem but I have searched and cannot find an answer.
I have a large table containing (simplified) Month, Project, Type, Value
Jan ProjectA X 15000,
Jan ProjectB X 2000,
Jan ProjectB Y 2000,
Jan ProjectC X 3000,
.....
Feb ProjectA X 15000,
Feb ProjectB Y 4000,
Feb ProjectC X 3000,
Feb ProjectD X 8989,
.....
Mar ProjectA X 15000,
Mar ProjectB Y 4000,
Mar ProjectC X 3000,
Mar ProjectD X 8989,
.....
I need a query which shows:
All projects+type in Jan but not Feb AND
All projects+type in Feb but not Jan AND
All projects+type in both but with different Values
I need it between any two months sorry for not being clear
Any help would be greatly appreciated (I have tried sub queries with NOT IN and joins but I feel that I am missing something simple as my queries became very large and still did not work)

You should be able to do this with aggregation:
select project, type,
(case when sum(case when month = 'jan' then 1 else 0 end) > 0 and
sum(case when month = 'feb' then 1 else 0 end) = 0
then 'Jan-Only'
when sum(case when month = 'jan' then 1 else 0 end) = 0 and
sum(case when month = 'feb' then 1 else 0 end) > 0
then 'Feb-Only'
when max(case when month = 'jan' then value else 0 end) <>
max(case when month = 'feb' then value else 0 end)
then 'Different'
end) as Which
from largetable lt
group by project, type;
Probably the easiest way to filter out the ones where the values are equal in jan and feb is to use a subquery:
select t.*
from (select project, type,
(case when sum(case when month = 'jan' then 1 else 0 end) > 0 and
sum(case when month = 'feb' then 1 else 0 end) = 0
then 'Jan-Only'
when sum(case when month = 'jan' then 1 else 0 end) = 0 and
sum(case when month = 'feb' then 1 else 0 end) > 0
then 'Feb-Only'
when max(case when month = 'jan' then value else 0 end) <>
max(case when month = 'feb' then value else 0 end)
then 'Different'
end) as Which
from largetable lt
where month in ('jan', 'feb')
group by project, type
) t
where Which is not null;

Related

Sum of particular column with month and year with fiscal year from custom date

I have following data in my table:
uniqueId d_date amount
1 2018-02-01 100.25
2 2019-03-01 456.5
3 2018-02-01 455
4 2019-05-01 200.48
5 2018-06-01 100
6 2019-07-01 200
7 2018-12-01 6950
8 2019-02-01 60
9 2020-01-20 100
Now when I enter start date = '2018-03-12' then my fiscal year must start with march 2018 to feb 2019 and so on.
If i enter start date = '2019-05-12' then my fiscal year must start with May 2019 to April 2020
I have tried below query but it is not working properly and also it calculate past year which is 2017 I do not want any data from past year from my entered custom date. So if entered start date = '2018-03-12' then is must start calculation for 2018 and above years only. No past year.
Declare #startdate as date
Declare #monthDate as int
Declare #ownmonth as int
set #startdate = '2018-03-12'
set #monthDate = month(#startdate)
set #ownmonth = 1
select
year(dateadd(month, -#monthDate, d_date)) year,
sum(case when month(d_date) = case when #monthDate+1 > 12 then #ownmonth else #monthDate+1 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+2 > 12 then #ownmonth+1 else #monthDate+2 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+3 > 12 then #ownmonth+2 else #monthDate+3 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+4 > 12 then #ownmonth+3 else #monthDate+4 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+5 > 12 then #ownmonth+4 else #monthDate+5 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+6 > 12 then #ownmonth+5 else #monthDate+6 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+7 > 12 then #ownmonth+6 else #monthDate+7 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+8 > 12 then #ownmonth+7 else #monthDate+8 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+9 > 12 then #ownmonth+8 else #monthDate+9 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+10 > 12 then #ownmonth+9 else #monthDate+10 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+11 > 12 then #ownmonth+10 else #monthDate+11 End then amount end) ,
sum(case when month(d_date) = case when #monthDate+12 > 12 then #ownmonth+11 else #monthDate+12 End then amount end) ,
sum(amount) total
from mytable
group by year(dateadd(month, -#monthDate, amount))
order by year
But above query does not show proper year & month wise data
Now I want output with fiscal year calculation:
Year Mar Apr May Jun July Aug Sept Oct Nov Dec Jan Feb Total
2018 - - - 100 - - - - - 6950 - 60 7110
2019 456.5 - 200.48 - 200 - - - - - 100 - 956.98
I can not use PIVOT as it is not supported in my compact SQL Server version.
How can I do this?
Your rule for a fiscal year is the year's March until the following year's February:
date | fiscal year
... | ...
2018-02-28 | 2017
2018-03-01 | 2018
... | 2018
2019-02-28 | 2018
2019-03-01 | 2019
... | ...
That means when we subtract two months from a date, we get a date the year of which is the fiscal year:
date | date - 2 months | fiscal year
... | ... | ...
2018-02-28 | 2017-12-28 | 2017
2018-03-01 | 2018-01-01 | 2018
... | ... | 2018
2019-02-28 | 2018-12-28 | 2018
2019-03-01 | 2019-01-01 | 2019
... | ... | ...
select
year(dateadd(month, -2, d_date)) as fiscal_year,
sum(case when month(d_date) = 3 then amount else 0 end) as mar,
sum(case when month(d_date) = 4 then amount else 0 end) as apr,
sum(case when month(d_date) = 5 then amount else 0 end) as may,
sum(case when month(d_date) = 6 then amount else 0 end) as jun,
sum(case when month(d_date) = 7 then amount else 0 end) as jul,
sum(case when month(d_date) = 8 then amount else 0 end) as aug,
sum(case when month(d_date) = 9 then amount else 0 end) as sep,
sum(case when month(d_date) = 10 then amount else 0 end) as oct,
sum(case when month(d_date) = 11 then amount else 0 end) as nov,
sum(case when month(d_date) = 12 then amount else 0 end) as dec,
sum(case when month(d_date) = 1 then amount else 0 end) as jan,
sum(case when month(d_date) = 2 then amount else 0 end) as feb,
sum(amount) as total
from mytable
group by year(dateadd(month, -2, d_date))
order by year(dateadd(month, -2, d_date));
If you want to limit this to the fiscal year a given date resides in, add:
where year(dateadd(month, -2, d_date)) = year(dateadd(month, -2, #given_date))
And well, if you want to limit this to the fiscal years beginning with that year, that would of course be:
where year(dateadd(month, -2, d_date)) >= year(dateadd(month, -2, #given_date))
UPDATE: You want a fiscal year to start with the first day of the month of a given date. I.e. If the given date is 1990-04-23, then a fiscal year starts with April. This changes above query only slightly, because rather than subtracting 2 months (for March), we must generalize this to subtracting one month less than the given month.
I am using a modulo operation when comparing months in order not to end up with months 13, 14, etc.
select
year(dateadd(month, - month(#startdate) + 1, d_date)) as fiscal_year,
sum(case when month(d_date) = (month(#startdate) + 0) % 12 then amount else 0 end) as first,
sum(case when month(d_date) = (month(#startdate) + 1) % 12 then amount else 0 end) as second,
sum(case when month(d_date) = (month(#startdate) + 2) % 12 then amount else 0 end) as third,
sum(case when month(d_date) = (month(#startdate) + 3) % 12 then amount else 0 end) as fourth,
sum(case when month(d_date) = (month(#startdate) + 4) % 12 then amount else 0 end) as fith,
sum(case when month(d_date) = (month(#startdate) + 5) % 12 then amount else 0 end) as sixth,
sum(case when month(d_date) = (month(#startdate) + 6) % 12 then amount else 0 end) as seventh,
sum(case when month(d_date) = (month(#startdate) + 7) % 12 then amount else 0 end) as eighth,
sum(case when month(d_date) = (month(#startdate) + 8) % 12 then amount else 0 end) as nineth,
sum(case when month(d_date) = (month(#startdate) + 9) % 12 then amount else 0 end) as tenth,
sum(case when month(d_date) = (month(#startdate) + 10) % 12 then amount else 0 end) as eleventh,
sum(case when month(d_date) = (month(#startdate) + 11) % 12 then amount else 0 end) as twelfth,
sum(amount) as total
from mytable
group by year(dateadd(month, - month(#startdate) + 1, d_date))
order by year(dateadd(month, - month(#startdate) + 1, d_date));
And again, if we want our results start from the fiscal year of the given date, we'd add:
where year(dateadd(month, - month(#startdate) + 1, d_date)) >= year(#startdate)

SQL I want to get the following output

I have a sales table
Date_s sales_man product qty
1-Jan-18 xx 01 30
1-Jan-18 xx 01 20
1-Jan-18 xy 01 20
1-Feb-18 xz 02 10
5-Feb-18 xz 02 30
1-Feb-18 xx 01 10
1-Feb-18 xx 01 40
1-Mar-18 xy 03 20
I want to get the following output data format as
Product sales_man Jan Feb Mar
01 xx 50 10 0
01 xy 20 0 0
02 xx 0 0 0
02 xy 0 0 0
02 xz 0 0 0
03 xy 0 0 20
You can use aggregation. Something like this:
select product, salesperson,
sum(case when extract(month from dates) = 1 then qty else 0 end) as jan,
sum(case when extract(month from dates) = 2 then qty else 0 end) as feb
from t
group by product, salesperson;
This uses ANSI SQL date functions, because your database tag is not clear. Date operations can differ by database.
Also, when looking at data by month, typically, you want to take the year into account as well (by filtering or aggregating on the year).
If i got Your problem right, you can try:
SELECT * into #TempTable FROM
(select product, salesman, qty, FORMAT(Dates, 'MMM') as Months from sales
) AS s
PIVOT
(
SUM(qty)
FOR Months in (Jan, Feb)
) AS Pvt
select product, salesman, isnull(Jan, 0) as Jan, isnull(Feb, 0) as Feb from
#TempTable order by product
drop table #TempTable
If you can change your date format from '1-Jan-18' to '1-01-18', then you can do below way
check sql fiddle
http://sqlfiddle.com/#!9/6d3824/2
If you consider below date format
'1-01-18',
'1-01-18',
'1-02-18';
then you can do this query
select product, salesman,
sum(case when extract(month from dates) = 1 then qty else 0 end) as jan,
sum(case when extract(month from dates) = 2 then qty else 0 end) as feb
from sales
group by product, salesman;
Result
product salesman jan feb
1 xx 30 0
1 xz 0 20
2 xy 10 0
For all month
http://sqlfiddle.com/#!9/6d3824/9
for all do query like this,
select product, salesman,
sum(case when extract(month from dates) = 1 then qty else 0 end) as jan,
sum(case when extract(month from dates) = 2 then qty else 0 end) as feb,
sum(case when extract(month from dates) = 3 then qty else 0 end) as mar,
sum(case when extract(month from dates) = 4 then qty else 0 end) as apr,
sum(case when extract(month from dates) = 5 then qty else 0 end) as may,
sum(case when extract(month from dates) = 6 then qty else 0 end) as jun,
sum(case when extract(month from dates) = 7 then qty else 0 end) as jul,
sum(case when extract(month from dates) = 8 then qty else 0 end) as aug,
sum(case when extract(month from dates) = 9 then qty else 0 end) as sep,
sum(case when extract(month from dates) = 10 then qty else 0 end) as oct,
sum(case when extract(month from dates) = 11 then qty else 0 end) as nov,
sum(case when extract(month from dates) = 12 then qty else 0 end) as dece
from sales
group by product, salesman;
Result would be
product salesman jan feb mar apr may jun jul aug sep oct nov dece
1 xx 30 0 0 0 0 0 0 0 0 0 0 0
1 xz 0 20 0 0 0 0 0 0 0 0 0 0
2 xy 10 0 0 0 0 0 0 0 0 0 0 0

Splits one column to multiple column according to data

I have a table which contains data of std attendance of one year
AttID Present absent. leave sick month StdRegNo
1. 23 1 0 0 JAN. 1
2. 25 0 0 0 JAN. 2
3. 23 0 0 0 MAR. 1
4. 21 3 0 1 MAR. 2
SO ON.......
I want result in such a view as bellow:
StdReq month P A L S month P A L S
1. Jan. 23 1 0 0 Mar 23 0 0 0
2. Jan. 25 0 0 0 Mar 21 3 0 1
I need this view for 12 months how can I do this? please help me
You can use a query like this:
select StdRegNo
-- January info
,max(case when [month] = 'JAN' then Present end) JAN_P
,max(case when [month] = 'JAN' then [absent] end) JAN_A
,max(case when [month] = 'JAN' then leave end) JAN_L
,max(case when [month] = 'JAN' then sick end) JAN_S
-- March info
,max(case when [month] = 'MAR' then Present end) MAR_P
,max(case when [month] = 'MAR' then [absent] end) MAR_A
,max(case when [month] = 'MAR' then leave end) MAR_L
,max(case when [month] = 'MAR' then sick end) MAR_S
-- And so on ...
from yourTable
group by StdRegNo;

SQL query to count incidents by year by month

I have one table called Incidents. I want a SQL query that returns the count of incidents split out by year, by month. The start year is 2010, however, the end year will be variable.
Example Incidents table:
DateLogged IncidentRef
----------- ------------
2015-04-05 1
2014-06-04 2
2013-01-01 3
2012-12-10 4
2011-10-15 5
2010-10-01 6
2012-12-11 7
2011-10-10 8
2010-10-10 9
Query Returns:
Year Jan Fev Mar Abr Mai Jun Jul Ago Set Out Nov Dez
2010 0 0 0 0 0 0 0 0 0 2 0 0
2011 0 0 0 0 0 0 0 0 0 2 0 0
2012 0 0 0 0 0 0 0 0 0 0 0 2
2013 1 0 0 0 0 0 0 0 0 0 0 0
2014 0 0 0 0 0 1 0 0 0 0 0 0
2015 0 0 0 1 0 0 0 0 0 0 0 0
How can I do that query? Where do I start?
One option is to use conditional aggregation:
select year(datelogged),
sum(case when month(datelogged) = 1 then 1 else 0 end) Jan,
sum(case when month(datelogged) = 2 then 1 else 0 end) Feb,
...,
sum(case when month(datelogged) = 12 then 1 else 0 end) Dec
from yourtable
group by year(datelogged)
SQL Fiddle Demo
With pivoting:
;with cte as(select year(date) y, month(date) m, ref from table)
select * from cte
pivot(count(ref) for m in([1],[2],...,[12]))p
Another way to do without a pivot you could use a join:
with years as
(
SELECT 2010 as y
UNION ALL
SELECT 2011
UNION ALL
SELECT 2012
UNION ALL
SELECT 2013
UNION ALL
SELECT 2014
UNION ALL
SELECT 2015
)
select years.y,
sum(case when month(DateLogged) = 1 then 1 else 0) as jan,
sum(case when month(DateLogged) = 2 then 1 else 0) as feb,
sum(case when month(DateLogged) = 3 then 1 else 0) as mar,
sum(case when month(DateLogged) = 4 then 1 else 0) as apr,
-- ...
sum(case when month(DateLogged) = 12 then 1 else 0) as dec,
from years y
left join incidents i on y.y = year(i.DateLogged)
group by y.DateLogged
If you want year to be "dynamic" you have the CTE like this
with years as
(
SELECT DISTINCT year(i.DateLogged) FROM incidents
)
but this has the same drawback as the sgeddes solution -- years with no values don't show up.
Using classic PIVOT:
Data:
CREATE TABLE #Incidents(
DateLogged DATE NOT NULL PRIMARY KEY
,IncidentRef INTEGER NOT NULL );
INSERT INTO #Incidents(DateLogged,IncidentRef) VALUES
('2015-04-05',1),('2014-06-04',2),('2013-01-01',3),
('2012-12-10',4),('2011-10-15',5),('2010-10-01',6),
('2012-12-11',7),('2011-10-10',8),('2010-10-10',9);
Query:
;WITH cte AS
(
SELECT [year] = YEAR(DateLogged),
[month] = CASE MONTH(DateLogged)
WHEN 1 THEN 'Jan' WHEN 2 THEN 'Fev'
WHEN 3 THEN 'Mar' WHEN 4 THEN 'Abr'
WHEN 5 THEN 'Mai' WHEN 6 THEN 'Jun'
WHEN 7 THEN 'Jul' WHEN 8 THEN 'Ago'
WHEN 9 THEN 'Set' WHEN 10 THEN 'Out'
WHEN 11 THEN 'Nov' WHEN 12 THEN 'Dez'
END,
IncidentRef
FROM #Incidents
)
SELECT [Year],Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, [Set], Out, Nov, Dez
FROM cte
PIVOT (
COUNT(IncidentRef)
FOR [month] IN (Jan, Fev, Mar, Abr, Mai, Jun,Jul, Ago, [Set], Out, Nov,Dez)
) AS piv;
LiveDemo
SQL Server 2012+
Using CHOOSE added UNION to cte to ensure to get zeros for missing years:
;WITH cte AS
(
SELECT [year] = YEAR(DateLogged),
[month] = CHOOSE(MONTH(DateLogged),'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'),
IncidentRef
FROM #Incidents
UNION ALL
SELECT [year], NULL, NULL
FROM (VALUES (2010),(2011),(2012),(2013),(2014),(2015)) AS t([year])
)
SELECT [Year],Jan, Fev, Mar, Abr, Mai, Jun, Jul, Ago, [Set], Out, Nov, Dez
FROM cte
PIVOT (
COUNT(IncidentRef)
FOR [month] IN (Jan, Fev, Mar, Abr, Mai, Jun,Jul, Ago, [Set], Out, Nov,Dez)
) AS piv
ORDER BY [Year];
LiveDemo2

Select distinct count usage divided by month

I do have a table license_Usage which works like a log of the usage of licenses in a day
ID User license date
1 1 A 22/1/2015
2 1 A 23/1/2015
3 1 B 23/1/2015
4 1 A 24/1/2015
5 2 A 22/2/2015
6 2 A 23/2/2015
7 1 B 23/2/2015
Where I want it to return the count of licenses of the day of the month with most usage of licenses the result should look like:
User Jan Feb
1 2 1 ...
2 0 2
I know I can get the total of licenses in a month using this query:
SELECT vlu.[Userkey],
COUNT(CASE WHEN MONTH = 1 THEN 1 END) as JAN,
COUNT(CASE WHEN MONTH = 2 THEN 1 END) as FEB,
COUNT(CASE WHEN MONTH = 3 THEN 1 END) as MAR,
COUNT(CASE WHEN MONTH = 4 THEN 1 END) as APR,
COUNT(CASE WHEN MONTH = 5 THEN 1 END) as MAY,
COUNT(CASE WHEN MONTH = 6 THEN 1 END) as JUN,
COUNT(CASE WHEN MONTH = 7 THEN 1 END) as JUL,
COUNT(CASE WHEN MONTH = 8 THEN 1 END) as AUG,
COUNT(CASE WHEN MONTH = 9 THEN 1 END) as SEP,
COUNT(CASE WHEN MONTH = 10 THEN 1 END) as OCT,
COUNT(CASE WHEN MONTH = 11 THEN 1 END) as NOV,
COUNT(CASE WHEN MONTH = 12 THEN 1 END) as DEC
FROM license_usage vlu
CROSS APPLY (SELECT MONTH(vlu.EndDate)) AS CA(Month)
WHERE vlu.[EndDate] >='2015-01-01'
AND vlu.[EndDate] < '2016-01-01'
GROUP BY vlu.[Userkey]
How can I get it to return my results?
Example:
http://sqlfiddle.com/#!3/be0b4/1
Got it by using distinct on the Count (*)
select umd.pbrUserkey,
max(case when mm = 1 then cnt else 0 end) as Jan,
max(case when mm = 2 then cnt else 0 end) as Feb,
max(case when mm = 3 then cnt else 0 end) as Mar,
max(case when mm = 4 then cnt else 0 end) as Apr,
max(case when mm = 5 then cnt else 0 end) as May
from (select vluk.pbrUserkey, month(vluk.EndDate) as mm, day(vluk.EndDate) as dd,
count(distinct vluk.idPackage) as cnt
from [license_usage] as vluk
where vluk.[EndDate] >= '2015-01-01' AND vluk.[EndDate] < '2016-01-01'
group by vluk.Userkey, month(vluk.EndDate), day(vluk.EndDate)
) umd
group by umd.Userkey;
If I understand correctly, you want the maximum by day usage per month for each user. The basic data you want is:
select UserKey, month(license_usage) as mm, day(license_usage) as dd,
count(distinct license) as cnt
from license_usage vlu
where vlu.EndDate] >= '2015-01-01' and vlu.EndDate < '2016-01-01'
group by UserKey, month(license_usage), day(license_usage);
Then you can pivot this in several ways, such as using conditional aggregation:
select UserKey,
max(case when mm = 1 then cnt else 0 end) as Jan,
. . .
from (select UserKey, month(license_usage) as mm, day(license_usage) as dd,
count(distinct license) as cnt
from license_usage vlu
where vlu.EndDate] >= '2015-01-01' AND vlu.EndDate < '2016-01-01'
group by UserKey, month(license_usage), day(license_usage)
) umd
group by UserKey;
CROSS APPLY is an interesting approach, but I can't think of a simpler way to get this information.