arithmetic operation on alias of column of table [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last month.
Improve this question
I have written a query which fetch the data like this and I wanted to calculate the opening and maindata I have formula for then which is ( CurrentEmp + Empjoined - EmpLeft ) as opening and ((EmpLeft*100)/((CurrentEmp+opening)/2)) as maindata respectively I have written it in query but I gets the error saying invalid column name .
month year CurrentEmp join leftemp
January 2021 10 2 1
February 2021 15 3 2
March 2021 20 5 2
and the output that I expect is
month year CurrentEmp join leftemp opening
January 2021 10 2 1 11
February 2021 15 3 2 16
March 2021 20 5 2 23
I have written the below code
with t0(n) as ( select n from ( values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) t(n)),ns as(select row_number()
over(order by t1.n) - 1 n from t0 t1, t0 t2, t0 t3),calendar as (
select top(12) DATEADD(month, n, '2021-01-01' ) dt , DATEADD(month, n , '2021-01-31')dd from ns order by n) select cast(DATENAME(month, dt) as nvarchar(max)) AS month,cast(DATENAME(YEAR, dt) as nvarchar(max))AS Year,
(SELECT COUNT(*) FROM EmployeeDetail e left join Separation s on e.Id = s.EmployeeId
WHERE (e.CompanyId=1 and e.DateOfJoining <calendar.dt and e.EmpStatus = 1) or(s.CompanyId = 1 and e.DateOfJoining <calendar.dt and s.LastWorkingDate >= calendar.dt)) AS CurrentEmp,
(select count(*) from EmployeeDetail where DateOfJoining >=calendar.dt And DateOfJoining<=calendar.dd and CompanyId = 1) as Empjoined,
(select count(*) from Separation where LastWorkingDate >= calendar.dt and LastWorkingDate < =calendar.dd and CompanyId =1) as EmpLeft,
(CurrentEmp+Empjoined-EmpLeft) as opening , cast (((EmpLeft*100)/((CurrentEmp+opening)/2)) as decimal(10,2)) as maindata
from calendar order by dt

An alias in the current select statement cannot be used as a variable within that same select statement.
You'll need to either:
Repeat the calculation:
(CurrentEmp+Empjoined-EmpLeft) as opening,
-- NOTE: opening IS REPLACED BY SAME CALC: (CurrentEmp+Empjoined-EmpLeft)
cast (((EmpLeft*100) /
((CurrentEmp+(CurrentEmp+Empjoined-EmpLeft))/2))
as decimal(10,2)) as maindata
Or, move the primary calculation of opening to a sub-query and join on that.
But, given the simplicity and low overhead of the calculation, I'd just repeat the calculation.

Related

Google BigQuery Dimensions SQL Multiple Grids

how would you select multiple grids in the example below instead of just one under "WHERE":
SELECT
sdg_code,
sdg_name,
"grid.5170.3" as grid,
year,
COUNT(DISTINCT id) as pubs,
ROUND(AVG(fcr), 1) as fcr,
ROUND(EXP(AVG(LOG(GREATEST(fcr, 1)))), 1) as fcr_geomean,
ROUND(sum(AltWithScore), 1) as altmetric
FROM
(
SELECT
p.id,
year,
if(p.altmetrics.score > 0, 1, 0) as AltWithScore,
cat_sdg.code as sdg_code,
cat_sdg.name as sdg_name,
p.metrics.field_citation_ratio as fcr,
p.altmetrics.score as altmetric_score,
row_number() over(partition by p.id, cat_sdg.code) as rn
FROM
dimensions - ai.data_analytics.publications p,
UNNEST(category_sdg.full) cat_sdg
WHERE
year >= 2011
AND year <= 2020
AND "grid.5170.3" in UNNEST(research_orgs)
)
WHERE rn = 1
GROUP BY
sdg_code,
sdg_name,
year
ORDER BY year asc
What needs to be changed:
It currently only runs for 1 organisation (GRID), I would like it to run for 11 organisations.
The org is identified with an ID called a “GRID”, it looks like this:
"grid.5170.3"
I want my new code to take 10 org IDs more. Need to use these 10:
grid.5254.6, grid.7048.b, grid.5117.2, grid.10825.3e, grid.4655.2, grid.11702.35, grid.154185.c, grid.475435.4, grid.7143.1, grid.27530.33
And add a column with the org name; currently there is only a column with the org.
Thanks, new to this whole thing.
Instead of WHERE year >= 2011 AND year <= 2020 AND "grid.5170.3" in UNNEST(research_orgs) use below
WHERE year >= 2011 AND year <= 2020
AND EXISTS (
SELECT 1
FROM UNNEST(research_orgs) grid
WHERE grid IN ('grid.5170.3', 'grid.5254.6', 'grid.7048.b', 'grid.5117.2', 'grid.10825.3e', 'grid.4655.2', 'grid.11702.35', 'grid.154185.c', 'grid.475435.4', 'grid.7143.1', 'grid.27530.33')
)

How to group by quarters(1 year = 4 quarters) in SQL? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Question Description:Show for each customer and product combination, the average sales quantities for 4 quarters,Q1, Q2, Q3 and Q4(in four separate columns) –Q1 being the first 3 months of the year (Jan, Feb & Mar), Q2 the next 3 months (Apr, May & Jun), and so on–ignore the YEAR component of the dates (i.e., 3/11/2001is considered the same date as 3/11/2002, etc.).Also compute the average for the “whole” year(again ignoring the YEAR component, meaning simply compute AVG) along with the total quantities(SUM) and the counts(COUNT).
table as follow:enter image description here
The sample result:enter image description here
I am a beginner on SQL and I met such a problem. It needs to group the 4 quarters just by using aggregate functions and group by clause.
with cte as (
select
customer,
product,
case
when (month < 4) then 'Q1'
when (month >= 4 AND month < 7) then 'Q2'
when (month >= 7 AND month < 10) then 'Q3'
when (month >= 10) then 'Q4'
end AS quarter,
quant
from bgg.table_sof
),
cte_full as (
select
customer,
product,
avg(quant) as average,
sum(quant) as total,
count(quant) as count
from bgg.table_sof
GROUP BY customer, product
)
select
cte_full.customer,
cte_full.product,
avg(cte1.quant) as Q1_AVG,
avg(cte2.quant) as Q2_AVG,
avg(cte3.quant) as Q3_AVG,
avg(cte4.quant) as Q4_AVG,
average,
total,
count
from cte_full
left join cte cte1 on cte_full.customer = cte1.customer and cte_full.product = cte1.product
left join cte cte2 on cte_full.customer = cte2.customer and cte_full.product = cte2.product
left join cte cte3 on cte_full.customer = cte3.customer and cte_full.product = cte3.product
left join cte cte4 on cte_full.customer = cte4.customer and cte_full.product = cte4.product
where cte1.quarter = 'Q1' OR cte2.quarter = 'Q2' OR cte3.quarter = 'Q3' OR cte4.quarter = 'Q4'
group by cte_full.customer, cte_full.product, average, total, count;
It's a tricky task for a beginner. My advice is to start with some theory and easy practice.
There is two CTE (common table expression):
the first is for defining quarters from months.
the second (cte_full) for calculating the last 3 columns in the result table.
And final select joins separately calculated avg by quarters to result.
I'm sure it isn't easy for understanding for beginner, feel free to ask.

SQL First In First Out Loyalty Point

fellow developers and analysts. I have some experience in SQL and have resorted to similar posts. However, this is slightly more niche. Thank you in advance for helping.
I have the below dataset (edited. Apology)
Setup
CREATE TABLE CustomerPoints
(
CustomerID INT,
[Date] Date,
Points INT
)
INSERT INTO CustomerPoints
VALUES
(1, '20150101', 500),
(1, '20150201', -400),
(1, '20151101', 300),
(1, '20151201', -400)
and need to turn it into (edited. The figures in previous table were incorrect)
Any positive amount of points are points earned whereas negative are redeemed. Because of the FIFO (1st in 1st out concept), of the second batch of points spent (-400), 100 of those were taken from points earned on 20150101 (UK format) and 300 from 20151101.
The goal is to calculate, for each customer, the number of points spent within x and y months of earning. Again, thank you for your help.
I have already answered a similar question here and here
You need to explode points earned and redeemed by single units and then couple them, so each point earned will be matched by a redeemed point.
For each of these matching rows calculate the months elapsed from the earning to the redeeming and then aggregate it all.
For FN_NUMBERS(n) it is a tally table, look at other answers I have linked above.
;with
p as (select * from CustomerPoints),
e as (select * from p where points>0),
r as (select * from p where points<0),
ex as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from e
join FN_NUMBERS(1000) on N<= e.points
),
rx as (
select *, ROW_NUMBER() over (partition by CustomerID order by [date] ) rn
from r
join FN_NUMBERS(1000) on N<= -r.points
),
j as (
select ex.CustomerID, DATEDIFF(month,ex.date, rx.date) mm
from ex
join rx on ex.CustomerID = rx.CustomerID and ex.rn = rx.rn and rx.date>ex.date
)
-- use this select to see points redeemed in current and past semester
select * from j join (select 0 s union all select 1 s ) p on j.mm >= (p.s*6)+(p.s) and j.mm < p.s*6+6 pivot (count(mm) for s in ([0],[2])) p order by 1, 2
-- use this select to see points redeemed with months detail
--select * from j pivot (count(mm) for mm in ([0],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) p order by 1
-- use this select to see points redeemed in rows per month
--select CustomerID, mm, COUNT(mm) PointsRedeemed from j group by CustomerID, mm order by 1
output of default query, 0 is 0-6 months, 1 is 7-12 (age of redemption in months)
CustomerID 0 1
1 700 100
output of 2nd query, 0..12 is the age of redemption in months
CustomerID 0 1 2 3 4 5 6 7 8 9 10 11 12
1 0 700 0 0 0 0 0 0 0 0 0 100 0
output from 3rd query, is the age of redemption in months
CustomerID mm PointsRedeemed
1 1 700
1 11 100
bye

Trouble running a complex query in sql?

I am pretty new to SQL Server and just started playing with it. I am trying to create a table that shows attendance percentage by department.
So first i run this query:
SELECT CrewDesc, COUNT(*)
FROM database.emp
INNER JOIN database.crew on sim1 = sim2
GROUP BY CrewDesc
This gives a table like this:
Accounting 10
Marketing 5
Economics 20
Engineering 5
Machinery 5
Tech Support 10
Then i run another query:
SELECT DeptDescription, COUNT(*)
FROM database.Attendee
GROUP BY DeptDescription
This gives me the result of all the people that have attended meeting something like
Accounting 8
Marketing 5
Economics 15
Engineering 10
Tech Support 8
Then I get the current week in the year by SELECT Datepart(ww, GetDate()) as CurrentWeek To make this example easy lets assume this will be week "2".
Now the way i was going to create this was a table for each step but that seems like waste. Is there a way we can combine to tables in a query? So in the end result i would like a table like this
Total# Attd Week (Total*Week) Attd/(Total*week)%
Accounting 10 8 2 20 8/20
Marketing 5 5 2 10 5/10
Economics 20 15 2 40 15/40
Engineering 5 10 2 10 10/10
Machinery 5 NULL 2 10 0/10
Tech Support 10 8 2 20 8/20
Ok, note that my recommendation below is based on your exact existing queries - there are certainly other ways to construct this that may be more performant, but functionally this should work for your requirement. Also, it illustrates the key features of different join types that happen to be relevant for your request, as well as inline views (aka nested queries), which are a super-powerful technique in the SQL language as a whole.
select t1.CrewDesc, t1.Total, t2.Attd, t3.Week,
(t1.Total*t3.Week) as Total_x_Week,
case when isnull(t1.Total*t3.Week, 0) = 0 then 0 else isnull(t2.Attd, 0) / isnull(t1.Total*t3.Week, 0) end as PercentageAttd
from (
SELECT CrewDesc, COUNT(*) AS Total
FROM database.emp INNER JOIN database.crew on sim1 = sim2
GROUP BY CrewDesc
) t1
left outer join /* left outer to keep all rows from t1 */ (
SELECT DeptDescription, COUNT(*) AS Attd
FROM database.Attendee GROUP BY DeptDescription
) t2
on t1.CrewDesc = t2.DeptDescription
cross join /* useful when adding a scalar value to all rows */ (
SELECT Datepart(ww, GetDate()) as Week
) t3
order by t1.CrewDesc
Good luck!
Try something like this
SELECT COALESCE(a.crewdesc,b.deptdescription),
a.total,
b.attd,
Datepart(ww, Getdate()) AS week,
total * Datepart(ww, Getdate()),
b.attd/(a.total*Datepart(ww, Getdate()))
FROM (query 1) a
FULL OUTER JOIN (query 2) b
ON a.crewdesc = b.deptdescription
WITH Total AS ( SELECT CrewDesc, COUNT(*) AS [Count]
FROM database.emp
INNER JOIN database.crew on sim1 = sim2
GROUP BY CrewDesc
),
Attd AS ( SELECT DeptDescription, COUNT(*) AS [Count]
FROM database.Attendee
GROUP BY DeptDescription
)
SELECT COALESCE(CrewDesc,DeptDescription) AS [Dept],
Total.[Count] AS [Total#],Attd.[Count] AS [Attd],
Total.[Count] * Datepart(ww, GetDate()) AS [(Total*Week)],
CAST(Attd.[Count] AS VARCHAR(10))+'/'+ CAST((Total.[Count] * Datepart(ww, GetDate()))AS VARCHAR(10)) AS [Attd/(Total*week)%]
FROM Total INNER JOIN Attd ON Total.CrewDesc = Attd.DeptDescription
I'm assuming your queries are correct -- you give no real information about your model so I've no way to know. They look wrong since the same data is called CrewDesc in one table and Dept in another. Also the join sim1 = sim2 seems very strange to me. In any case given the queries you posted this will work.
With TAttend as
(
SELECT CrewDesc, COUNT(*) as TotalNum
FROM database.emp
INNER JOIN database.crew on sim1 = sim2
GROUP BY CrewDesc
), Attend as
(
SELECT DeptDescription, COUNT(*) as Attd
FROM database.Attendee
GROUP BY DeptDescription
)
SELECT CrewDesc as Dept, TotalNum, ISNULL(Attd, 0) as Attd ,Datepart(ww, GetDate()) as Week,
CASE WHEN ISNULL(Attd, 0) > 0 THEN 0
ELSE ISNULL(Attd, 0) / (TotalNum * Datepart(ww, GetDate()) ) END AS Percent
FROM TAttend
LEFT JOIN Attend on CrewDesc = DeptDescription

How to group difference of date values by range [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
I have strung together a series of queries that I have had working as individual queries or as a query with one subquery.
I need to show the total number of jobs that have a particular status grouped by range of the number of days a job has been in that status.
E.g. (random data for concept purpose)
fldFranchiseCode Status 0-9 10-19 20-29 etc
Franchise A Status1 1 0 3
Franchise A Status2 2 1 4
Franchise A Status4 3 2 1
Franchise B Status2 1 6 4
This is what I have so far, but I'm getting a SQL error - 'Incorrect syntax near 'pvt'.'
SELECT * FROM
(SELECT fldFranchiseCode, Range AS [Day Range], COUNT(*) AS Jobs
FROM (SELECT fldFranchiseCode, CASE WHEN Days BETWEEN 0 AND 9 THEN '0- 9'
WHEN Days BETWEEN 10 AND 19 THEN '10-19'
WHEN Days BETWEEN 20 AND 29 THEN '20-29'
WHEN Days BETWEEN 30 AND 39 THEN '30-39'
WHEN Days BETWEEN 40 AND 49 THEN '40-49'
WHEN Days BETWEEN 50 AND 59 THEN '50-59'
WHEN Days BETWEEN 60 AND 69 THEN '60-69'
WHEN Days BETWEEN 70 AND 79 THEN '70-79'
WHEN Days BETWEEN 80 AND 89 THEN '80-89'
WHEN Days BETWEEN 90 AND 99 THEN '90-99'
ELSE 'Over 100' END AS Range
FROM (SELECT fldRecordID,
T.fldInquiryRecordID,
fldDate,
NextDate,
DATEDIFF("D", fldDate, NextDate) AS Days,
fldStatus,
fldFranchiseCode
FROM ( SELECT fldRecordID,
T1.fldInquiryRecordID,
fldDate,
( SELECT MIN([fldDate])
FROM tblStatusLog T2
WHERE T2.[fldInquiryRecordID] = T1.[fldInquiryRecordID]
AND T2.[fldDate] > T1.[fldDate]
) AS NextDate,
fldStatus,
fldFranchiseCode
FROM tblStatusLog T1
JOIN tblInquiry ON T1.fldInquiryRecordID = tblInquiry.fldInquiryRecordID
) AS T
GROUP BY [Day Range],fldFranchiseCode) q1
pivot
(max(jobs)
FOR [Day Range] IN ([0- 9],[10-19],[20-29],[30-39],[40-49],[50-59],
[60-69],[70-79],[80-89],[90-99],[Over 100])
)as pvt
Any help much appreciated
Proper indenting will help identify the syntax error. (Well, or avoiding nesting queries four levels deep in the first place.)
SELECT * FROM
(
SELECT fldFranchiseCode, ...
FROM
(
SELECT fldFranchiseCode, CASE ...
FROM
(
SELECT fldRecordID, ...
FROM
(
SELECT fldRecordID, ...
FROM tblStatusLog T1
JOIN tblInquiry ON T1.fldInquiryRecordID = tblInquiry.fldInquiryRecordID
) AS T
GROUP BY Range, fldFranchiseCode
^^^^^ note, can't group by an alias here
) q1
) AS q2 -- you need this one
) AS q3 -- and this one too
pivot
(
max(jobs)
FOR [Day Range] IN ([0- 9],[10-19],[20-29],[30-39],[40-49],[50-59],
[60-69],[70-79],[80-89],[90-99],[Over 100])
) as pvt;