ROW_NUMBER() without over in SQL - database

Is there any way to use ROW_NUMBER() in SQL without using OVER, because I want to use sorting.
I have a Grid with multiple sortable columns with configurable rows. In my scenario order by is variable that's why I am not able to put order by using ROWNUM.

select ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as number from Task order by RuleId

I approached this using a different logic. Instead of checking for every single day and verifying it is a weekday or a holiday I create a table which lists only the business days and then take the nth value.
CREATE OR REPLACE FUNCTION add_n_working_days (
start_date DATE, working_days PLS_INTEGER
) RETURN DATE AS
l_end_date DATE := start_date;
l_counter pls_integer := 0;
BEGIN
SELECT
business_day
INTO l_end_date
FROM
(
WITH
dates AS
(SELECT start_date + level - 1 as dt FROM dual CONNECT BY level < 100)
,weekdates AS
(SELECT dt as weekday FROM dates WHERE TO_CHAR(dt,'fmdy') NOT IN ('sat','sun'))
,business_days AS
(
SELECT weekday as business_day FROM weekdates
MINUS
SELECT holiday FROM so_holidays
)
SELECT business_day, ROW_NUMBER() OVER (ORDER BY 1) as rn from business_days
)
WHERE rn = working_days + 1;
RETURN l_end_date;
END add_n_working_days;
If working_days gets too high then I suggest making that value 100 a variable.

select
a.City,
a.len
from
(
select city,length(city) AS len,
row_number()over(order by length(city) desc, city) as hi,
row_number()over(order by length(city), city) as lo
from
STATION) as a where (a.lo=1 or a.hi=1);

Related

How to use Pivot with RowNumber and date

I have a SQL Server table like this:
How can I change reading column into 2 columns based on rownumber?
I have tried like this:
WITH pivot_data AS
(
SELECT
date, CurrentMeterSNID,
1 + ((ROW_NUMBER() OVER (PARTITION BY CurrentMeterSNID ORDER BY date desc) - 1) % 2) rownum,
Reading
FROM
INF_Facility_ElectricalRecord
)
SELECT
date, CurrentMeterSNID, [1], [2]
FROM
pivot_data
PIVOT
(MAX(Reading) FOR rownum IN ([1], [2])) AS p;
but the result that I get is:
I get Null record; how can I replace that null value with record from a day after the date?
actually you are not doing PIVOT. You just want to conditionally display the value on different column. For this you use the CASE statement.
For the second requirement : for the NULL value, showing subsequent day value, you can use LEAD() or LAG() window function. This is the else part of the case
select date, CurrentMeterSNID,
[1] = case when rownum2 = 1
then reading
else lead(reading) over(partition by CurrentMeterSNID order by date)
end,
[2] = case when rownum2 = 2
then reading
else lead(reading) over(partition by CurrentMeterSNID order by date)
end
from INF_Facility_ElectricalRecord
As long as you are displaying every date in that query, you can't have what you want.
So you have to pick the max(date) in other words where rownumber will be 1.
WITH pivot_data AS(
SELECT date,CurrentMeterSNID,
1 + ((row_number() over(partition by CurrentMeterSNID ORDER by date desc) - 1) % 2) rownum,
Reading
FROM dbo.Table_1 )
, T2 AS
(
SELECT CurrentMeterSNID, date, [1], [2]
FROM pivot_data PIVOT (max(Reading) FOR rownum IN ([1],[2])) AS p
)
SELECT CurrentMeterSNID, Max(date), MAX([1]), Max([2])
FROM T2
GROUP BY CurrentMeterSNID

UNION Returns NULL When First SELECT Returns Nothing

Hi I have a table: T1 that contains two columns Date and Price
T1
---------------------------
DATE | PRICE |
---------------------------
2018-07-25 |2.00 |
---------------------------
2018-06-20 |3.00 |
---------------------------
2017-05-10 |3.00 |
---------------------------
Here are my requirements:
If a user enters a date that is not in the DB I need to return the last price and date in the table T1.
If a user enters a date that is superior or inferior to one of the dates in the table T1 -- for example if a user enters '2017-05-09' which is not in the table; I have to return the next date above the given date. In this case'2017-05-10'
I am using UNION in my script but it returns empty when one of the SELECT statements returns empty.
I am using a CTE table:
DECLARE #DateEntered DATE
WITH HistoricalCTE (Date, Price, RowNumber) AS (
SELECT R.Date,
R.Price,
ROW_NUMBER() OVER (PARTITION BY R.Date, R.Price ORDER BY Date DESC)
FROM T1 R
WHERE Date = #DateEntered
UNION
SELECT R.Date,
R.Price,
ROW_NUMBER() OVER (PARTITION BY R.Date, R.Price ORDER BY Date DESC)
FROM T1 R
WHERE Date < #DateEntered
UNION
SELECT R.Date,
R.Price,
ROW_NUMBER() OVER (PARTITION BY R.Date, R.Price ORDER BY Date DESC)
FROM T1 R
WHERE Date > #DateEntered
)
The issue is when I enter superior to all the dates in the table T1, I get an empty result because the first select is returning empty. Any idea about how I would solve this?
You might be overcomplicating this. If I read your question correctly, we can just take the smallest value greater than the input, or if that doesn't exist, then just take the max of the table.
WITH cte AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY Date) rn
FROM T1
WHERE Date > #DateEntered
)
SELECT
CASE WHEN EXISTS (SELECT 1 FROM cte WHERE rn = 1)
THEN (SELECT Date FROM cte WHERE rn = 1)
ELSE (SELECT MAX(Date) FROM T1) END AS Date,
CASE WHEN EXISTS (SELECT 1 FROM cte WHERE rn = 1)
THEN (SELECT Price FROM cte WHERE rn = 1)
ELSE (SELECT Price FROM T1 WHERE Date = (SELECT MAX(Date) FROM T1)) END AS Price;
Demo
All the edge cases seem to be working in the above demo, and you may test any input date against your sample data.

SQL - How can I Group sets of sequential numbers and return the MIN and Max Dates

this is driving me crazy! does anyone know how to write some SQL that will return the MIN and MAX dates from groups of sequential numbers? please see screen shots below.
This is the SQL I used:
SELECT
num
, empid
, orderdate
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY orderdate) AS Num
, empid
, orderdate
FROM TSQL.Sales.Orders)T1
WHERE empid = 4
This is what it returns:
What I would like to do is get the Min and Max dates for each set of sequential numbers based on the num column. For example: the first set would be num 3, 4, 5 & 6. so the Min date is 2006-07-08 and the Max date is 2006-07-10
See example of results needed below
Any help with this would be much appreciated, thank you in advance
Update
I have now changed the SQL to do what I needed: example as follows:
Select
empid
, Island
, MIN(orderdate) as 'From'
, Max(orderdate) as 'To'
From
(select
empid
, num
, num - ROW_NUMBER() OVER (ORDER BY num, orderdate) as Island
, orderdate
from
(Select
ROW_NUMBER() OVER (ORDER BY orderdate) as Num
, empid
, orderdate
from TSQL.Sales.Orders)T1
where empid = 4
)T2
group By
empid
, Island
Result
Thank you so much for your help on this, I have been trying this for ages
Regards
Jason
This should do it:
;with dateSequences(num, empId, orderDate) as
(
select ROW_NUMBER() over (order by orderdate) as num
, empId
, orderdate
from yourTable
),
dateGroups(groupNum, empId, orderDate, num) as
(
select currD.num, currD.empid, currD.orderDate, currD.num
from dateSequences currD
left join dateSequences prevD on prevD.num = currD.num - 1 and prevD.empid = currD.empId
where prevD.num is null
union all
select dg.groupNum, d.empId, d.orderDate, d.num
from dateSequences d
inner join dateGroups dg on dg.num + 1 = d.num and d.empId = dg.empId
)
select empId, min(orderDate) as MinDate, max(orderDate) as MaxDate
from dateGroups
where empId = 4
group by empId, groupNum
Basically it first makes a CTE to get the row numbers for each row in date order. Then it makes a recursive CTE that first finds all the groups with no previous sequential entries then adds all subsequent entries to the same group. Finally it takes the records with all the group numbers assigned and groups them by their group number and gets the min and max dates.

Get record with MAX date

I have a data looks like this from my database. My report will have 2 parameters, Start Date and End Date.
For example if the user select Start Date = 1/1/2015 and End Date = 12/31/2015, the report should return user TierCode = Privilege.
I've achieve this using Stored Procedure. But the performance is an issues here as I couldn't use Extract Data.
SELECT
m.MemberID,
ty.TierCode AS TierCodeTY,
ly.TierCode AS TierCodeLY
FROM
Tangs_dim_Member m LEFT JOIN
(
SELECT TierCode, MemberID, ROW_NUMBER() OVER(PARTITION BY MemberID ORDER BY SnapshotDate DESC) AS i
FROM dw_Tangs_MonthlySnapshot
WHERE SnapshotDate >= #StartDate AND SnapshotDate <= #EndDate
) ty
ON
ty.MemberID = m.MemberID AND ty.i = 1 LEFT JOIN
(
SELECT TierCode, MemberID, ROW_NUMBER() OVER(PARTITION BY MemberID ORDER BY SnapshotDate DESC) AS i
FROM dw_Tangs_MonthlySnapshot
WHERE SnapshotDate >= DATEADD(year,-1,#StartDate) AND SnapshotDate <= DATEADD(year,-1,#EndDate)
) ly
ON
ly.MemberID = m.MemberID AND ly.i = 1
How can I achieve above report without using Stored Procedure. Calculated field is fine as long I can use Views / Custom Query / Tables + Extract Data. So the data will be filtered at Tableau instead at the database.
I think you can get the last inserted record by adding Ordered by [date]
and get just first one by adding [Limit 1] in the sql query
hope that help you

In SQL Server how can I fetch all rows with a date greater than some set date or at least 20 rows

I'm looking for a way to fetch at least 20 rows, regardless of the date or all rows with a date greater than a set date (whichever of the 2 fetches the most rows).
For example:
SELECT *
FROM table1
WHERE the_date >= '2014-11-01'
ORDER BY the_date DESC
will give me what I want, but if this returns less than 20 rows then I want to keep going before that date until I get 20 (or until there are no more rows - whichever comes first).
I could just select all and take the ones I need programatically, but I'm trying to avoid that as that would be a major change to the actual code in many places.
Can this be done?
Note: I am using SQL Server 2008.
Here's an approach:
select *
from
(
select row_number() over (order by the_date desc) num, t.*
from table1 t
) i
where i.the_date >= '2014-11-01'
or i.num < 21
Very strange requirement but something like this should work.
DECLARE #Date date = '2014-11-01';
with MyResults as
(
SELECT *, 1 as RowNum
FROM table1
WHERE (the_date >= #Date )
UNION ALL
SELECT top 10 *, ROW_NUMBER() over(order by the_date desc)
FROM table1
order by the_date desc
)
Select *
from MyResults
where RowNum <= 20
The right answer was almost there, but the user has removed it, so here it is again:
SELECT *
FROM table1
WHERE the_date >= '2014-11-01'
union
SELECT top 20 *
FROM table1
ORDER BY the_date desc
The removed answer had union all
This answer has a problem with duplicate dates , but with the data I have that is not an issue

Resources