As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have table xyz, and I have 13 columns namely emplid, jan,feb… dec.
here I have data as below
EMPLID JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC
123 0 0 0 0 0 5 5 2 6 0 0 0
456 0 2 3 0 0 0 5 5 3 0 0 0
789 5 0 0 5 0 5 0 5 6 3 0 4
ABC 4 5 0 5 5 0 5 0 6 0 0 0
Now I need to write a query so that I get the output as the very first month for which some data is entered other than 0
For eg : if I check for EMPLID 123, I should get output as JUN (because JUN is the very first month for this EMPLID where data is other than 0)
Similarly for 456, it would be FEB, for 789 and ABC its JAN.
As Philipp says in his comment, your table structure is definitely to be changed. Other wise you will run into lots of issues like this in future..
To answer your question, you could try this:
select case when JAN > 0 then 'JAN'
when FEB > 0 then 'FEB'
when MAR > 0 then 'MAR'
when APR > 0 then 'APR'
when MAY > 0 then 'MAY'
when JUN > 0 then 'JUN'
when JUL > 0 then 'JUL'
when AUG > 0 then 'AUG'
when SEP > 0 then 'SEP'
when OCT > 0 then 'OCT'
when NOV > 0 then 'NOV'
when DEC > 0 then 'DEC'
end as Month
from xyz
where EMPLID='456'
SQL Fiddle demo
First of all I recommend to refactor like Philipp mentioned:
Use one table like this:
EMPLID MONTH VALUE
123 1 3
123 12 5
In this case its more easy to query:
SELECT [MONTH]
FROM YourTable
GROUP BY EMPLID, [MONTH]
HAVING VALUE > 0
AND MIN([MONTH]) = [MONTH]
If you don't have another choise use a case:
SELECT
CASE
WHEN JAN > 0 THEN 'JAN'
WHEN FEB > 0 THEN 'FEB'
WHEN MAR > 0 THEN 'MAR'
WHEN APR > 0 THEN 'APR'
WHEN MAY > 0 THEN 'MAY'
WHEN JUN > 0 THEN 'JUN'
WHEN JUL > 0 THEN 'JUL'
WHEN AUG > 0 THEN 'AUG'
WHEN SEP > 0 THEN 'SEP'
WHEN OCT > 0 THEN 'OCT'
WHEN NOV > 0 THEN 'NOV'
WHEN DEC > 0 THEN 'DEC'
ELSE 'No Month found'
END AS FirstMonth
FROM YourTable
As Philipp said, it's better to use a different structure for your table.
Working with the current structure you can do something like this:
Select a.EMPLID, case when (select b.JAN from tbl b where a.EMPLID=b.EMPLID) > 0 then 'JAN'
when.....etc(the same for each month).... end as Val
from tbl a
Probably this isn't the best solution but it should work.
Related
I am having a dataframe which consists of month wise sales data for many parts:
For eg
Partno Month Qty
Part 1 June 2019 20
Part 1 July 2019 25
Part 1 Sep 2019 30
Part 2 Mar 2019 45
Part 3 Aug 2019 40
Part 3 Nov 2019 21
I want to convert this data into a month by month time series, which makes it easier for time series forecasting, Once I make it into a ts object
Month Part1 Part 2 Part 3
Jan 0 0 0
Feb 0 0 0
Mar 0 45 0
Apr 0 0 0
May 0 0 0
June 20 0 0
July 25 0 0
Aug 0 0 0
Sept 0 30 0
Oct 0 0 20
Nov 0 0 21
Dec 0 0 0
I am quite baffled as to how this can be carried out in R. Any solutions for the same would be highly useful, as I plan build some forecasting models in R.
Looking forward to hearing from you all!
Assume the data DF shown reproducibly in the Note at the end.
First convert DF to zoo splitting it by the first column and converting the Month column to yearmon class. Then convert that to ts class, extend it to Jan to Dec, and set any NAs to 0. (If you don't need the 0 months at the beginning and end omit the yrs and window lines.)
library(zoo)
z <- read.zoo(DF, split = 1, index = 2, FUN = as.yearmon, format = "%b %Y")
tt <- as.ts(z)
yrs <- as.integer(range(time(tt))) # start and end years
tt <- window(tt, start = yrs[1], end = yrs[2] + 11/12, extend = TRUE)
tt[is.na(tt)] <- 0
tt
giving:
Part 1 Part 2 Part 3
Jan 2019 0 0 0
Feb 2019 0 0 0
Mar 2019 0 45 0
Apr 2019 0 20 0
May 2019 0 0 0
Jun 2019 20 0 0
Jul 2019 25 0 0
Aug 2019 0 0 0
Sep 2019 30 0 0
Oct 2019 0 0 20
Nov 2019 0 0 21
Dec 2019 0 0 0
Note
Lines <- "Partno, Month, Qty
Part 1, Jun 2019, 20
Part 1, Jul 2019, 25
Part 1, Sep 2019, 30
Part 2, Mar 2019, 45
Part 2, Apr 2019, 20
Part 3, Oct 2019, 20
Part 3, Nov 2019, 21"
DF <- read.csv(text = Lines, strip.white = TRUE)
I have some code for a pivot table but I also want to times (x) it buy another table if it full into the criteria.
select *
from
(SELECT
year(dteOccupiedDate) as [year],
moveincharge as type ,
left(datename(month,dteOccupiedDate),3)as [month],
MoveInCharge
FROM dav.Gainshare where strTenancyType = 'LTO' and dteOccupiedDate between '2020-04-01' and '2021-03-31' and moveincharge is not null
) as s
PIVOT
(
count(moveincharge)
FOR [month] IN (jan, feb, mar, apr,
may, jun, jul, aug, sep, oct, nov, dec)
)AS pvt
order by year
this code shows
year type jan feb mar apr may jun jul aug sep oct nov dec
2020 Single 0 0 0 5 1 4 12 12 6 0 0 0
2020 Family 0 0 0 5 1 4 12 12 6 0 0 0
2020 Early-leave 0 0 0 5 1 4 12 12 6 0 0 0
2020 Re-house 0 0 0 5 1 4 12 12 6 0 0 0
they are 4 different moveincharge types when it fallin that type I want it X times by the
single (150)
family (200)
rehouse (130)
early leave (140)
I can also make these into a table if that make it better.
I want to see this
year type jan feb mar apr may jun jul aug sep oct nov dec
2020 Single 0 0 0 750 150 600 1800 1800 900 0 0 0
fo example Type Single for July is 12 x 150 because single is worth 150 each and there are 12 in that month
I much prefer conditional aggregation over the bespoke pivot syntax. This is easily accomplished with a join:
select year(gs.dteOccupiedDate) as [year],
sum(case when month(gs.dteOccupiedDate) = 1 then v.charge else 0 end) as jan,
sum(case when month(gs.dteOccupiedDate) = 2 then v.charge else 0 end) as feb,
. . .
from dav.Gainshare gs join
(values ('single', 150), ('family', 200), . . .
) v(moveincharge, charge)
on gs.movincharge = v.ovincharge
where gs.strTenancyType = 'LTO' and
gs.dteOccupiedDate between '2020-04-01' and '2021-03-31' and
gs.moveincharge is not null
group by year(gs.dteOccupiedDate);
Note: This will return two rows -- one for 2020 and one for 2021. That is what your query does. You might want to remove the group by and the year from the select.
I would like to create an annual sales report table by sales rep, showing all the twelve month. The data I have is more or less like in this example:
id | rep | date | price
----------------------------
1 1 2017-01-01 20
2 1 2017-01-20 44
3 2 2017-02-18 13
4 2 2017-03-08 12
5 2 2017-04-01 88
6 2 2017-09-05 67
7 3 2017-01-31 10
8 3 2017-06-01 74
The result I need would be like this:
Rep Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
----------------------------------------------------
1 64 0 0 0 0 0 0 0 0 0 0 0
2 0 13 12 88 0 0 0 0 67 0 0 0
3 10 0 0 0 0 74 0 0 0 0 0 0
What would be the most efficient way to write this query?
One way:
select rep,
sum(case when extract('month' from date) = 1 then price else 0 end ) as Jan,
sum(case when extract('month' from date) = 2 then price else 0 end ) as Feb
-- another months here
from t
group by rep
One way is to use windowed functions with FILTER:
SELECT DISTINCT
"rep",
COALESCE(SUM(price) FILTER (WHERE extract('month' from "date") = 1) OVER(PARTITION BY "rep"),0) AS Jan,
COALESCE(SUM(price) FILTER (WHERE extract('month' from "date") = 2) OVER(PARTITION BY "rep"),0) AS Feb
--....
FROM ta;
Rextester Demo
Warning!
You probably want to partition by YEAR too to avoid summing JAN 2017 and JAN 2018.
How to populate or display the result for each month?
I have a table with four columns
Plan Status Creation date Triggers
I need to get the results for each plan each month how many triggers count are there. my report should look like this.
Plan Jan feb march Apr may jun jul aug sep oct nov dec Totaol
001 2 0 1 1 0 1 1 1 2 3 1 7 21
002 2 0 1 1 0 1 1 1 2 3 1 7 21
003 2 0 1 1 0 1 1 1 2 3 1 7 21
Could you please help me out how to achieve this results?
Thanks in advance.
select
plan,
sum(case when datepart(mm,[Creation date]) = 1 then 1 else 0 end) as Jan,
sum(case when datepart(mm,[Creation date]) = 2 then 1 else 0 end) as Feb,
...
sum(triggers) as Total
from table
where Status = 'SomeStatus'
group by Plan
I have this query
With
NoOfOrder as
(
SELECT Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,Jan,Feb,Mar
FROM
(
select LEFT(datename(month,InvoiceDate),3) mon,InvoiceNo as InvoiceNo
from tbl_InvoiceMain ,tbl_OrderMain,tbl_CompanyMaster
where tbl_InvoiceMain.OrderID = tbl_OrderMain.OrderID
and (CAST(tbl_InvoiceMain.InvoiceDate AS date) BETWEEN tbl_CompanyMaster.YearStart AND tbl_CompanyMaster.YearEnd)
) P
PIVOT (count(InvoiceNo)for mon in (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)) PV
),
OnTime as
(
SELECT Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,Jan,Feb,Mar
FROM
(
select LEFT(datename(month,InvoiceDate),3) mon,InvoiceNo as InvoiceNo
from tbl_InvoiceMain ,tbl_OrderMain,tbl_CompanyMaster
where tbl_InvoiceMain.OrderID = tbl_OrderMain.OrderID
and (CAST(tbl_InvoiceMain.InvoiceDate AS date) BETWEEN tbl_CompanyMaster.YearStart AND tbl_CompanyMaster.YearEnd)
and CAST(tbl_InvoiceMain.InvoiceDate AS date) <= CAST(tbl_OrderMain.ScheduledDispatchDate AS date)
) P
PIVOT (count(InvoiceNo)for mon in (Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec)) PV
)
Select * From NoOfOrder
union all
Select * From OnTime
It gives this result:
Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar
18 35 39 52 32 47 47 22 14 0 0 0
9 10 16 22 6 11 19 10 5 0 0 0
Here is my expected result
Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb Mar
NoOfOrder 18 35 39 52 32 47 47 22 14 0 0 0
OnTimeDelivered 9 10 16 22 6 11 19 10 5 0 0 0
DeliverPerformance% 50.00 28.57 41.03 42.31 18.75 23.40 40.43 45.45 35.71 0.00 0.00 0.00
The formula for DeliverPerformance is:
DeliverPerformance% = (OnTimeDelivered/NoOfOrder) X 100
How do I achieve this result on the next row?
for reference you check my question in good format
enter link description here
My immediate suggestion is to combine everything first prior to pivoting the results.
Your first query might look like this:
SELECT
LEFT(datename(month, InvoiceDate), 3) InvMon,
SUM(1) AS NoOfOrder,
SUM(CASE WHEN CAST(tbl_InvoiceMain.InvoiceDate AS date) <= CAST(tbl_OrderMain.ScheduledDispatchDate AS date) THEN 1 ELSE 0 END) OnTimeDelivered
FROM tbl_InvoiceMain, tbl_OrderMain, tbl_CompanyMaster
WHERE tbl_InvoiceMain.OrderID = tbl_OrderMain.OrderID
AND (CAST(tbl_InvoiceMain.InvoiceDate AS date) BETWEEN tbl_CompanyMaster.YearStart AND tbl_CompanyMaster.YearEnd)
GROUP BY LEFT(datename(month, InvoiceDate), 3)
Note that I'm always counting every invoice record and optionally counting the "on time" invoices with that CASE statement and the respective SUM functions.
My next thought is to put that query in a CTE and then the statement that uses that CTE will do the additional calculation like so:
SELECT InvMon, NoOfOrder, OnTimeDelivered, ((OnTimeDelivered / NoOfOrder) * 100) DeliverPerformance ...
And finally, that's what I pivot.