I have the following SQL Server query on which i'm having some trouble using ROW_NUMBER().
Select
ROW_NUMBER() OVER (Partition by R.DriverName, CASE WHEN Sum(R.Points) > 0 THEN 1 ELSE 0 END Order By E.EventDate ASC) As 'RowID',
CASE WHEN Sum(R.Points) > 0 THEN 1 ELSE 0 END As 'PointsId',
R.DriverName,
R.EventID,
Format(E.EventDate, 'dd/MM/yyyy') as 'Event Date'
From Races R
Inner Join Events E
On E.EventID = R.EventID
Where R.SeriesID Like 'FOE' And E.EventType Like 'R' And R.DriverName Like 'Lucas di Grassi'
Group By R.DriverName, R.EventID, E.EventDate
Order By E.EventDate
And get the following result:
I want that after each 0 on PointsId Column, the RowID resets to 1 and adds up again until the next 0.
Can anyone help?
Thank you,
VĂtor
You need nested Analytic Functions:
Select
ROW_NUMBER() OVER (Partition by R.DriverName, grp Order By E.EventDate ASC) As 'RowID',
...
from
(
Select
-- assign a number to each group of rows
SUM(CASE WHEN Sum(R.Points) > 0 THEN 1 ELSE 0 END)
OVER (Partition by R.DriverName
Order By E.EventDate ASC) As grp,
...
From Races R
Inner Join Events E
On E.EventID = R.EventID
Where R.SeriesID Like 'FOE' And E.EventType Like 'R' And R.DriverName Like 'Lucas di Grassi'
Group By R.DriverName, R.EventID, E.EventDate
) as dt
Order By E.EventDate
Related
The below query is working fine in Oracle but it is not working in hive.
SELECT Q.tm_mo_id,
'1380' AS mrc_cd,
NVL (R.itm_profit_ctr_cd, '99') AS profit_center_cd,
MAX(CASE R.itm_profit_ctr_cd
WHEN NULL THEN 'UNASSIGN PROFIT CNTR'
ELSE R.itm_profit_ctr_ds
END) profit_center_desc,
SUM(Q.bp_grs_quota_am) AS mth_bp_plan_gts_am_usd,
SUM(Q.grs_quota_am) AS mth_ju_plan_gts_am_usd
FROM v_l_0002_gb_gds_us_quota_v_1 Q
LEFT JOIN
(SELECT * FROM
(SELECT ph_dtl_id,
itm_profit_ctr_cd,
MIN (itm_profit_ctr_ds) AS itm_profit_ctr_ds,
ROW_NUMBER () OVER (
PARTITION BY ph_dtl_id
ORDER BY COUNT(CASE profit_ctr_cd
WHEN 'JNJDUMMY' THEN NULL
WHEN '99' THEN NULL
ELSE profit_ctr_cd
END) DESC,
itm_profit_ctr_cd ASC) rn
FROM v_l_0002_gb_gds_us_sku_to_profit_center_lookup_v_1
GROUP BY ph_dtl_id,
itm_profit_ctr_cd) E
WHERE rn = 1 ) R
ON (Q.ph_dtl_id = R.ph_dtl_id)
WHERE SUBSTR (Q.tm_mo_id, 1, 4) = '2016'
GROUP BY Q.tm_mo_id,
NVL(R.itm_profit_ctr_cd, '99')
I have looked at related Qs on Stack.
I am trying to sort my query to display month in ascending order. A similar post on Stack said that I must indicate "ASC", but this doesn't work for me. I have written an Order By. I cannot figure out why it is not working.
SELECT DATENAME( MONTH,(Submission.SubmissionDate)) AS [Date]
FROM Submission
GROUP BY DATENAME( MONTH,(Submission.SubmissionDate)) ORDER BY [Date] ASC;
This is the output:
Month
August
February
September
Note: this is just a part of my query, I didnt think it would necessary to show the rest, which relates to other attributes from my table (Not month related)
Edit: This is my Entire Query: (The Initial One)
SELECT DATENAME( MONTH,(Submission.SubmissionDate)) AS [Date],
SUM( CASE WHEN Submission.Status='Under review' THEN 1 ELSE 0 END) [Under_Review],
SUM( CASE WHEN Submission.Status='Accepted' THEN 1 ELSE 0 END) [Accepted],
SUM( CASE WHEN Submission.Status='Rejected' THEN 1 ELSE 0 END) [Rejected],
SUM( CASE WHEN Submission.Status='In print' THEN 1 ELSE 0 END) [In_print],
SUM( CASE WHEN Submission.Status='Published' THEN 1 ELSE 0 END) [Published]
FROM Submission INNER JOIN ((Faculty INNER JOIN School ON Faculty.FacultyID = School.[FacultyID]) INNER JOIN (Researcher INNER JOIN ResearcherSubmission ON Researcher.ResearcherID = ResearcherSubmission.ResearcherID) ON School.SchoolID = Researcher.SchoolID) ON Submission.SubmissionID = ResearcherSubmission.SubmissionID
GROUP BY DATENAME( MONTH,(Submission.SubmissionDate))
ORDER BY DATENAME( MONTH,(Submission.SubmissionDate));
SELECT DATENAME( MONTH, Submission.SubmissionDate) AS [Date]
FROM Submission
ORDER BY datepart(mm,Submission.SubmissionDate)
You don't need a group by (for the query shown). Also, when you order by month name it would return results in the alphabetical order of month name. You should not use previously defined aliases in the where,order by having and group by clauses.
Edit: The problem is with the join conditions. You should correct them as per the comments in line.
SELECT DATENAME( MONTH,(Submission.SubmissionDate)) AS [Date],
SUM( CASE WHEN Submission.Status='Under review' THEN 1 ELSE 0 END) [Under_Review],
SUM( CASE WHEN Submission.Status='Accepted' THEN 1 ELSE 0 END) [Accepted],
SUM( CASE WHEN Submission.Status='Rejected' THEN 1 ELSE 0 END) [Rejected],
SUM( CASE WHEN Submission.Status='In print' THEN 1 ELSE 0 END) [In_print],
SUM( CASE WHEN Submission.Status='Published' THEN 1 ELSE 0 END) [Published]
FROM Faculty
INNER JOIN School ON Faculty.FacultyID = School.[FacultyID]
INNER JOIN Researcher ON School.SchoolID = Researcher.SchoolID
INNER JOIN ResearcherSubmission ON Researcher.ResearcherID = ResearcherSubmission.ResearcherID
INNER JOIN SUBMISSION ON Submission.SubmissionID = ResearcherSubmission.SubmissionID
GROUP BY DATENAME( MONTH,(Submission.SubmissionDate))
ORDER BY DATEPART( MONTH,(Submission.SubmissionDate))
A simple option is to add MONTH(Submission.SubmissionDate) to your group by clause, and order by that as well:
SELECT DATENAME( MONTH,(Submission.SubmissionDate)) AS [Date]
FROM Submission
GROUP BY MONTH(Submission.SubmissionDate), DATENAME( MONTH,(Submission.SubmissionDate))
ORDER BY MONTH(Submission.SubmissionDate)
This will work for your real query as well.
You can use MIN() or MAX():
SELECT DATENAME(MONTH,(Submission.SubmissionDate)) AS [Date]
FROM Submission
GROUP BY DATENAME(MONTH,(Submission.SubmissionDate))
ORDER BY MIN([Date]) ASC;
This chooses an arbitrary date from each group and orders by that.
By the way, you probably should care about the year as well as the month. If so:
SELECT YEAR(s.SubmissionDate), DATENAME(MONTH, s.SubmissionDate) AS [Date]
FROM Submission s
GROUP BY YEAR(s.SubmissionDate), DATENAME(MONTH, s.SubmissionDate)
ORDER BY MIN([Date]) ASC;
I'm not able to use where condition on the row number within the same select statement. Results are not consistent if I use a different select statement for applying condition over the rownumber...
SELECT TOP (#lastrow - 1) c.totalRows
,c.ae_effective_enrollment_id
,c.[user_id]
,c.login_name
,c.first_name
,c.last_name
,cm.courseware_title
,cm.courseware_code
,#courseware_id assetId
,c.enrollment_status_id
,CASE
WHEN c.enrollment_status_id = 2
AND c.is_self_enrolled = 0
THEN 'Admin-' + s.description
WHEN c.enrollment_status_id = 2
AND c.is_self_enrolled = 1
THEN 'Self-' + s.description
ELSE s.description
END AS enrollmentStatus
,c.is_group
,CASE
WHEN c.is_self_enrolled = 0
THEN 1
ELSE 0
END is_admin
,CASE
WHEN c.auma_is_assigned = 1
THEN 'Admin-assigned'
WHEN c.auma_is_assigned = 0
THEN 'Self-assigned'
ELSE 'No-My-Plan'
END AS myplanStatus
, master_assignment_id
,ROW_NUMBER() over(partition by cm.courseware_id,c.user_id order by c.is_self_enrolled)as check_row
FROM enrollmentCTE c
INNER JOIN dbo.courseware_master cm ON cm.courseware_id = #courseware_id
LEFT JOIN #statuscodes s ON s.id = c.enrollment_status_id
WHERE check_row=1 and
enrollment_status_id<>4 and
rownumber > #firstrow
AND rownumber < #lastrow
ORDER BY rownumber
check_row here is not recognised. Please help
SQL order of execution.
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
the check_row alias was made in the select part so it doesn't exist yet in the context
EDIT
done some testing. can't seem to get it right. as a temporary solution you could attempt to put the
ROW_NUMBER() over(...
in the where clause aswell
EDIT:
another option from the MSDN website is
Returning a subset of rows
The following example calculates row numbers for all rows in the SalesOrderHeader table in the order of the OrderDate and returns only rows 50 to 60 inclusive.
USE AdventureWorks2012;
GO
WITH OrderedOrders AS
(
SELECT SalesOrderID, OrderDate,
ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNumber
FROM Sales.SalesOrderHeader
)
SELECT SalesOrderID, OrderDate, RowNumber
FROM OrderedOrders
WHERE RowNumber BETWEEN 50 AND 60;
SELECT totalRows, ae_effective_enrollment_id, user_id, login_name, first_name, last_name, check_row FROM
(SELECT TOP (#lastrow - 1) c.totalRows as totalRows
,c.ae_effective_enrollment_id as ae_effective_enrollment_id
,c.[user_id] as user_id
,c.login_name as login_name
,c.first_name as first_name
,c.last_name as last_name
,cm.courseware_title as courseware_title
,cm.courseware_code as courseware_code
,#courseware_id as assetId
,c.enrollment_status_id as enrollment_status_id
,CASE
WHEN c.enrollment_status_id = 2
AND c.is_self_enrolled = 0
THEN 'Admin-' + s.description
WHEN c.enrollment_status_id = 2
AND c.is_self_enrolled = 1
THEN 'Self-' + s.description
ELSE s.description
END AS enrollmentStatus
,c.is_group
,CASE
WHEN c.is_self_enrolled = 0
THEN 1
ELSE 0
END is_admin
,CASE
WHEN c.auma_is_assigned = 1
THEN 'Admin-assigned'
WHEN c.auma_is_assigned = 0
THEN 'Self-assigned'
ELSE 'No-My-Plan'
END AS myplanStatus
, master_assignment_id
,ROW_NUMBER() over(partition by cm.courseware_id,c.user_id order by c.is_self_enrolled)as check_row
FROM enrollmentCTE c
INNER JOIN dbo.courseware_master cm ON cm.courseware_id = #courseware_id
LEFT JOIN #statuscodes s ON s.id = c.enrollment_status_id
WHERE enrollment_status_id<>4 and
rownumber > #firstrow
AND rownumber < #lastrow
ORDER BY rownumber ) t where check_row = 1
NOTE - add all column name in first select statement
Use CTE to make your query based on another
;WITH CTE AS(
SELECT c.totalRows
,c.ae_effective_enrollment_id
,c.[user_id]
,c.login_name
,c.first_name
,c.last_name
,cm.courseware_title
,cm.courseware_code
,#courseware_id assetId
,c.enrollment_status_id
,CASE
WHEN c.enrollment_status_id = 2
AND c.is_self_enrolled = 0
THEN 'Admin-' + s.description
WHEN c.enrollment_status_id = 2
AND c.is_self_enrolled = 1
THEN 'Self-' + s.description
ELSE s.description
END AS enrollmentStatus
,c.is_group
,CASE
WHEN c.is_self_enrolled = 0
THEN 1
ELSE 0
END is_admin
,CASE
WHEN c.auma_is_assigned = 1
THEN 'Admin-assigned'
WHEN c.auma_is_assigned = 0
THEN 'Self-assigned'
ELSE 'No-My-Plan'
END AS myplanStatus
, master_assignment_id
,ROW_NUMBER() over(partition by cm.courseware_id,c.user_id order by c.is_self_enrolled) as check_row
FROM enrollmentCTE c
INNER JOIN dbo.courseware_master cm ON cm.courseware_id = #courseware_id
LEFT JOIN #statuscodes s ON s.id = c.enrollment_status_id
WHERE enrollment_status_id<>4
AND rownumber > #firstrow
AND rownumber < #lastrow
)
SELECT TOP (#lastrow - 1) *
FROM CTE
WHERE check_row = 1
ORDER BY rownumber
for a list of purchaser email addresses, I am trying to return one line per purchaser that has the columns '1stOrderDate', '2ndOrderDate', '3rdOrderDate' and 'TotalNumberofOrders'
I have tried using the ROW_Number function in the WHERE clause of subqueries but it reports that Windowed functions aren't allowed in the WHERE clause, so any help on how I fill in the ???s below would be gratefully received!
SELECT
PT.email AS 'Email',
MIN(OT.orderdate) AS '1stOrderDate',
??? AS '2ndOrderDate',
??? AS '3rdOrderDate',
COUNT(DISTINCT OT.order_reference) AS 'TotalNumberOfOrders'
FROM dbo.Orders AS OT
JOIN dbo.Purchaser AS PT ON OT.account_reference = PT.account_reference
GROUP BY PT.Email
You can do this with row_number() and conditional aggregation:
SELECT PT.email,
MAX(CASE WHEN seqnum = 1 THEN OT.OrderDate END) as OrderDate_1,
MAX(CASE WHEN seqnum = 2 THEN OT.OrderDate END) as OrderDate_2,
MAX(CASE WHEN seqnum = 3 THEN OT.OrderDate END) as OrderDate_3,
COUNT(DISTINCT OT.order_reference) AS TotalNumberOfOrders
FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY account_reference ORDER BY o.orderdate) as seqnum
FROM dbo.Orders o
) OT JOIN
dbo.Purchaser PT
ON OT.account_reference = PT.account_reference
GROUP BY PT.Email
A couple of notes:
Don't use single quotes for column aliases. Instead, choose column names that do not require escaping.
For the segnum = 1 logic, you can use MIN(), but I think consistency is a benefit here.
EDIT:
My guess is that the problem is the difference between a account_reference and email. Try this:
SELECT email,
MAX(CASE WHEN seqnum = 1 THEN OT.OrderDate END) as OrderDate_1,
MAX(CASE WHEN seqnum = 2 THEN OT.OrderDate END) as OrderDate_2,
MAX(CASE WHEN seqnum = 3 THEN OT.OrderDate END) as OrderDate_3,
COUNT(DISTINCT OT.order_reference) AS TotalNumberOfOrders
FROM (SELECT o.*, ROW_NUMBER() OVER (PARTITION BY pt.email ORDER BY o.orderdate) as seqnum
FROM dbo.Orders o JOIN
dbo.Purchaser PT
ON OT.account_reference = PT.account_reference
) OT
GROUP BY PT.Email
I am trying to count events (which are rows in the event_table) in the year before and the year after a particular target date for each person. For example, say I have a person 100 and target date is 10/01/2012. I would like to count events in 9/30/2011-9/30/2012 and in 10/02/2012-9/30/2013.
My query looks like:
select *
from (
select id, target_date
from subsample_table
) as i
left join (
select id, event_date, count(*) as N
, case when event_date between target_date-365 and target_date-1 then 0
when event_date between target_date+1 and target_date+365 then 1
else 2 end as after
from event_table
group by id, target_date, period
) as h
on i.id = h.id
and i.target_date = h.event_date
The output should look something like:
id target_date after N
100 10/01/2012 0 1000
100 10/01/2012 1 0
It's possible that some people do not have any events in the before or after periods (or both), and it would be nice to have zeros in that case. I don't care about the events outside the 730 days.
Any suggestions would be greatly appreciated.
I think the following may approach what you are trying to accomplish.
select id
, target_date
, event_date
, count(*) as N
, SUM(case when event_date between target_date-365 and target_date-1
then 1
else 0
end) AS Prior_
, SUM(case when event_date between target_date+1 and target_date+365
then 1
else 0
end) as After_
from subsample_table i
left join
event_table h
on i.id = h.id
and i.target_date = h.event_date
group by id, target_date, period
This is a generic answer. I don't know what date functions teradata has, so I will use sql server syntax.
select id, target_date, sum(before) before, sum(after) after, sum(righton) righton
from yourtable t
join (
select id, target_date td
, case when yourdate >= dateadd(year, -1, target_date)
and yourdate < target_date then 1 else 0 end before
, case when yourdate <= dateadd(year, 1, target_date)
and yourdate > target_date then 1 else 0 end after
, case when yourdate = target_date then 1 else 0 end righton
from yourtable
where whatever
group by id, target_date) sq on t.id = sq.id and target_date = dt
where whatever
group by id, target_date
This answer assumes that an id can have more than one target date.