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
There are 3 tables
Students(student_id, st_name)
Subjects(subject_id,sub_name)
Marks(st_id,sub_id,Score)
Write an SQL query to display the student name, average score of the student, maximum mark obtained by the student , name of the subject in which the student has scored maximum marks.
Below is the code I wrote
I am getting the errors -Column 'students.name' and 'subjects.name' are invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
select students.st_name as Students_Name,avg(Score) as Average, max(Score) as Maximum,subjects.sub_name as Max_Subject_name
from marks
join students on students.student_id=marks.st_id
join subjects on subjects.subject_id=marks.sub_id
join
(
select st_id,avg(score) as Average,max(score) as Maximum from marks group by st_id
) as x on x.st_id=marks.st_id
order by students.st_name,subjects.sub_name;
Try this
;with cte as
(
select students.st_name as Students_Name
,students.student_id
,RANK() over(partition by students.student_id order by marks.score desc) as seq
,subjects.sub_name as Max_Subject_name
,Marks.Score
from marks
INNER join students
on students.student_id=marks.st_id
INNER join subjects
on subjects.subject_id=marks.sub_id
)
select
Students_Name
,student_id
,Max_Subject_name
,Score
,(select avg(score) from cte b where b.student_id=a.student_id) as average
from cte a
where seq=1
Try
select students.name as Students_Name
,avg(Score) as Average
,max(Score) as Maximum
,subjects.name as Max_Subject_name
from marks
INNER join students
on students.student_id=marks.st_id
INNER join subjects
on subjects.subject_id=marks.st_id
GROUP BY students.name
,subjects.name
order by students.name
,subjects.name;
or if you want your query:
select students.name as Students_Name,x.Average, x.Maximum,subjects.name as Max_Subject_name
from marks
join students on students.student_id=marks.st_id
join subjects on subjects.subject_id=marks.st_id
join
(
select st_id,avg(score) as Average,max(score) as Maximum from marks group by st_id
) as x on x.st_id=marks.st_id
order by students.name,subjects.name;
Related
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 year.
Improve this question
Is there a way to get the final payment for a customer same payment key for 2 different account types with the same amount paid in the SQL Server?
SELECT
p.Amount,
t.date,
p.PayKey,
t.BillKey
FROM
Transaction t
INNER JOIN
payment p ON t.PayKey = p.PayKey
LEFT JOIN
BillTable b ON t.BillKey = b.Sbillkey
AND t.Tbillkey = b.BillKey
WHERE
t.BillKey in (123457, 1786243)
My results
Amount date PayKey BillKey
----------------------------------------
2540.00 2020-02-06 762944 123457
2540.00 2020-02-06 762944 1786243
But the final results I would like to obtain is :
Amount date PayKey
-------------------------------
2540.00 2020-02-06 762944
Add a Group By.
SELECT
p.Amount,
t.date,
p.PayKey
FROM
Transaction t
INNER JOIN
payment p ON t.PayKey = p.PayKey
LEFT JOIN
BillTable b ON t.BillKey = b.Sbillkey
AND t.Tbillkey = b.BillKey
WHERE
t.BillKey in (123457, 1786243)
GROUP BY
p.Amount,
t.date,
p.PayKey
Or use Distinct to return unique rows
SELECT DISTINCT
p.Amount,
t.date,
p.PayKey
FROM
Transaction t
INNER JOIN
payment p ON t.PayKey = p.PayKey
LEFT JOIN
BillTable b ON t.BillKey = b.Sbillkey
AND t.Tbillkey = b.BillKey
WHERE
t.BillKey in (123457, 1786243)
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 3 years ago.
Improve this question
(Submitting the following as both an attempt at info-share of best practices as well as a request for additional opinions...)
Q: I need to run a query that gets the exchange rate for a transaction. Based on the date of the transaction, I need the latest exchange rate from a rate history table where the starting effective date for the rate is less than the transaction's date.
Very basically:
SELECT t.Amount, t.TrxDate, t.Currency, ex.ExchangeRate
FROM Transactions t
LEFT JOIN LATERAL (
SELECT ExchangeRate
FROM RateHistory h
WHERE t.TrxDate <= h.EffectiveDate AND t.Currency = h.Currency ORDER BY EffectiveDate DESC
LIMIT 1) ex
The problem comes in with the LIMIT 1. I can't have this subquery returning multiple rows, I only need the most recent exchange rate. Using LIMIT 1 or attempting to use ROW_NUMBER() and a conditional join both result in the same "Unsupported subquery" error.
Anyone have any recommendations? The query works just fine elsewhere, but not in Snowflake.
Here is the actual query. The last subquery is the issue.
SELECT
'SG' AS Region,
CAST(gl.acct_no AS NUMERIC(12,6)) AS acct_no,
gl.trx_date,
source,
gl.reference,
doc_no,
gl.amount,
for_amt,
reference2,
gl.reg_int_id,
gl.reg_seq_no,
gl.curr_id AS gl_curr_id,
c.curr_id AS chart_curr_id,
z.reference AS reference3,
z.dist_dt,
cur.cur_desc,
ex.exchng_rate
FROM gltrx gl
JOIN chart c ON ROUND(c.acct_no,6) = ROUND(gl.acct_no,6)
LEFT OUTER JOIN currencies cur ON gl.curr_id = cur.curr_id
LEFT JOIN LATERAL (SELECT MAX(ap.reference) AS reference, MIN(aph.dist_dt) AS dist_dt
FROM apdist ap
LEFT OUTER JOIN aphist aph ON ap.voucher_no = aph.voucher_no
WHERE ap.reg_int_id = gl.reg_int_id AND ap.reg_seq_no = gl.reg_seq_no) z
LEFT JOIN LATERAL (SELECT Exchng_rate
FROM Curr_hist
WHERE Curr_Id = gl.curr_id
AND Exchng_Dt <= gl.trx_date
ORDER BY exchng_dt DESC
LIMIT 1) ex
Recommendation 1: Tried below query with returned one row successfully, both emp and dept tables have two rows each.
SELECT * FROM EMP WHERE DEPTNO = (SELECT DEPTNO FROM DEPT LIMIT 1)
So we can use LIMIT in subquery, there is no issue with LIMIT, issue is somewhere else.
Try to break query into pieces, and run each piece individually and then combine them one-by one to analyze.
Response To Recommendation 1: That subquery works, however the issue is with the LEFT JOIN LATERAL. I have tried my query without the LIMIT 1 and it works fine... except it obviously returns too many results.
Recommendation 2: Any Specific reason we are using LATERAL?
Try writing subquery using with clause and join it later.
Response to Recommendation 2: Using LATERAL because I need exactly one record from the subquery to join to each record in the transaction table. LATERAL allows for the conditional aggregation to achieve that. I'm not quite sure what you mean by using the WITH clause. Are you suggesting a CTE?
Recommendation 3: Maybe you can try removing LATERAL and also use MAX function instead of sorting subquery and getting limit, because essentially you need the latest rate after specified date but that was max by date will give you.
SELECT t.Amount, t.TrxDate, t.Currency, ex.ExchangeRate
FROM Transactions t
LEFT JOIN (
SELECT MAX(h.EffectiveDate ), h.Currency
FROM RateHistory h
WHERE t.TrxDate <= h.EffectiveDate
AND t.Currency = h.Currency
GROUP BY h.Currency
) ex
Response to Recommendation 3: Since what I need is the the exchange rate for the max date, I'd need to select the exchange rate in that subquery as well, which means it would need to be grouped by and I'd end up in the same place; too many joins.
Are there any other recommendations and/or work-arounds available out there??
use a window function to make sure you get only 1 row?
(SELECT Exchng_rate,
RANK() OVER (ORDER BY exchng_dt DESC) as order
FROM Curr_hist
WHERE Curr_Id = gl.curr_id
AND Exchng_Dt <= gl.trx_date
)
where order=1
So I moved the first LATERAL to a CTE which might not have been the problem.
The second LATERAL is needing each rows gl.tx_date so if you just LEFT JOIN on that (which gives to way to many rows) and then use the ROW_NUMBER() to implement the filter you wanted with the LIMIT 1. Which makes me think this will be slow, but should work.
WITH cte_a AS (
SELECT ap.reg_int_id
,ap.reg_seq_no
,MAX(ap.reference) AS reference
,MIN(aph.dist_dt) AS dist_dt
FROM apdist ap
LEFT OUTER JOIN aphist aph
ON ap.voucher_no = aph.voucher_no
GROUP BY 1,2
)
SELECT Region,
acct_no,
trx_date,
source,
reference,
doc_no,
amount,
for_amt,
reference2,
reg_int_id,
reg_seq_no,
gl_curr_id,
chart_curr_id,
reference3,
dist_dt,
cur_desc,
exchng_rate
FROM (
SELECT
'SG' AS Region,
CAST(gl.acct_no AS NUMERIC(12,6)) AS acct_no,
gl.trx_date,
source,
gl.reference,
doc_no,
gl.amount,
for_amt,
reference2,
gl.reg_int_id,
gl.reg_seq_no,
gl.curr_id AS gl_curr_id,
c.curr_id AS chart_curr_id,
z.reference AS reference3,
z.dist_dt,
cur.cur_desc,
ex.exchng_rate
row_number() over (partition by gl.curr_id order by ex.exchng_dt DESC) as rn
FROM gltrx gl
JOIN chart c
ON ROUND(c.acct_no,6) = ROUND(gl.acct_no,6)
LEFT OUTER JOIN currencies cur ON gl.curr_id = cur.curr_id
LEFT JOIN cte_a as z
ON z.reg_int_id = gl.reg_int_id AND z.reg_seq_no = gl.reg_seq_no
LEFT JOIN Curr_hist as ex
ON ex.Curr_Id = gl.curr_id and ex.Exchng_Dt <= gl.trx_date
)
WHERE rn = 1;
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 5 years ago.
Improve this question
This is my query:
select
Sno, TopEmpName, HighLevel, TopEmpID, CH, ED, DIR, GM, AGM, BDM, SMM, LowEmpID
from
(select
projectallocation.proAllocationID as Sno,
temp.intro_name as TopEmpName,
projectallocation.introtoplevelEmpid as TopEmpID,
temper.csshortname as HighLevel,
companystructure.csshortname as Level,
introducermaster.intro_name as LowEmpName,
projectallocation.introlevelEmpid as LowEmpID
from
projectallocation
inner join
dbo.IntroducerMaster on dbo.introducermaster.empid = projectallocation.introLevelEmpid
inner join
introducermaster as temp on temp.empiD = projectallocation.introtopLevelEmpid
inner join
companyStructure on projectallocation.introleveID = companyStructure.HLevel
inner join
companystructure as temper on projectallocation.introtoplevelID = temper.Hlevel
where
projectallocation.projectID = 1
group by
IntroducerMaster.Intro_Name, temp.intro_name,
companyStructure.CSShortName, projectallocation.proAllocationID,
projectallocation.introlevelEmpid, projectallocation.introtoplevelEmpid,
projectallocation.introtoplevelID, temper.csshortname
order by
projectallocation.introtoplevelID asc
) b
PIVOT
(max(LowEmpName)
for level in (CH, ED, DIR, GM, AGM, BDM, SMM)
) PVT
Where do I put an Order by clause ?
I want order BY CH,ED,.... for topempname
"The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified."
It is clearly stating that you can't order it when you have derived table and sub queries.
To apply ORDER BY, wrap the output to inside a SELECT and apply your ORDER BY condition like following.
SELECT *
FROM (select Sno,
TopEmpName,
HighLevel,
TopEmpID,
CH,
ED,
DIR,
GM,
AGM,
BDM,
SMM,
LowEmpID
from (select projectallocation.proAllocationID as Sno,
temp.intro_name as TopEmpName,
projectallocation.introtoplevelEmpid as TopEmpID,
temper.csshortname as HighLevel,
companystructure.csshortname as Level,
introducermaster.intro_name as LowEmpName,
projectallocation.introlevelEmpid as LowEmpID
from projectallocation
inner join dbo.IntroducerMaster
on dbo.introducermaster.empid =
projectallocation.introLevelEmpid
inner join introducermaster as temp
on temp.empiD =
projectallocation.introtopLevelEmpid
inner join companyStructure
on projectallocation.introleveID =
companyStructure.HLevel
inner join companystructure as temper
on projectallocation.introtoplevelID =
temper.Hlevel
where projectallocation.projectID = 1
group by IntroducerMaster.Intro_Name,
temp.intro_name,
companyStructure.CSShortName,
projectallocation.proAllocationID,
projectallocation.introlevelEmpid,
projectallocation.introtoplevelEmpid,
projectallocation.introtoplevelID,
temper.csshortname) b
PIVOT (Max(LowEmpName)
for level in (CH,
ED,
DIR,
GM,
AGM,
BDM,
SMM) ) PVT) T
ORDER BY CH,ED
I have two tables: tickets with unique ticket id and tickethistory with multiple records of a ticket (like open,attend,forward,close etc). Want to get records of
customers whose current ticket is open and last closed ticket is within 5 days gap. Using following query gives multiple records of closed tickets. Want last closed ticket actiondate in order to calculate days gap. If current open ticket and last closed ticket are within 5 days gap, want to consider current ticket as repeated.
SELECT A.ticketId,A.username,A.status,A.areaName,A.subject
,d.deptId,d.action,d.actionDate odate,g.actionDate cdate,g.status
FROM tb_tickets A
INNER JOIN (SELECT action, actiondate, ticketId, deptId FROM tb_ticketHistory WHERE action='Open') d
on a.ticketId = d.ticketid
INNER JOIN (SELECT th.ticketid, tt.username, tt.status, actiondate FROM tb_ticketHistory th
INNER JOIN tb_tickets tt
on th.ticketId = tt.ticketId WHERE th.action='closed') g
on a.username = g.username
WHERE d.deptId=5 AND a.status!='closed'
ORDER BY ticketId ASC
Since you haven't give exact structure and sample data, it's tough to give an exact answer. but you can try following code by tweaking it as your structure -
select CurrentOpenTickets.customerid, CurrentOpenTickets.ticketid from
(
select customerid, t.ticketid, actiondate from [dbo].[tb_ticketHistory ] th
inner join [dbo].[tb_Tickets] t on t.ticketid = th.ticketid
where t.status != 'C'
) CurrentOpenTickets
inner join
(select customerid, t.ticketid, actiondate from [dbo].[tb_ticketHistory ] th
inner join [dbo].[tb_Tickets] t on t.ticketid = th.ticketid
where th.status = 'C'
) PastClosedTickets
on CurrentOpenTickets.customerid = PastClosedTickets.customerid and datediff(DAY, CurrentOpenTickets.actiondate, PastClosedTickets.actiondate) <= 5
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 9 years ago.
Improve this question
I'm using this query, but I get an error vdagbk.bedrag and vdagbk.reden .
Problem is, if I would put in in the second SELECT the result would certainly be wrong as it sums the result to many times due to double data in the table.
SELECT TOP (100) PERCENT
SUM(P.bedrag) AS ex,
C.dosno,
C.dosnm,
SUM(P.betaald) AS TotBetaald,
SUM(CASE vdagbk.reden WHEN 'H' THEN vdagbk.bedrag END) AS Expr1
FROM
dbo.verkopen AS P
INNER JOIN
(SELECT DISTINCT
dbo.doss.dosno, dbo.doss.dosnm, dbo.verkopen.ino
FROM dbo.verkopen
INNER JOIN dbo.doss ON dbo.verkopen.ino = dbo.doss.ino
INNER JOIN dbo.vdagbk ON dbo.verkopen.ino = dbo.vdagbk.ino
WHERE
(dbo.doss.uitvoerder LIKE 'LL')
AND (dbo.doss.dosno LIKE '101520')
GROUP BY
dbo.doss.dosno, dbo.doss.dosnm, dbo.verkopen.ino) AS C ON C.ino = P.ino
INNER JOIN
dbo.vdagbk AS vdagbk_1 ON P.ino = vdagbk_1.ino
GROUP BY
C.dosno, C.dosnm
How can I make this query work ?
You're giving your table dbo.vdagbk an alias vdagbk_1 here:
INNER JOIN
dbo.vdagbk AS vdagbk_1 ON P.ino = vdagbk_1.ino
so you also need to use that alias in your SUM() clause here:
SUM(CASE vdagbk.reden WHEN 'H' THEN vdagbk.bedrag END) AS Expr1
Change this to:
SUM(CASE vdagbk_1.reden WHEN 'H' THEN vdagbk_1.bedrag END) AS Expr1
and it should work.