T-SQL: WHERE clause in OVER(PARTITION BY... ORDER BY...) - sql-server

I have the following query
;WITH tmp AS
(
SELECT *, ROW_NUMBER()
OVER
(PARTITION BY to_tel, duration, call_date
ORDER BY rates_start DESC) as rn
FROM ##TempTable
)
SELECT *
FROM tmp
WHERE rn = 1
ORDER BY customer_id, to_code, duration
But I would like to modify it where it doesn't give me the maximum rates_start, but the maximum rates_start before a certain date. Is there any way I can do this?

You can add WHERE inside the cte part. I'm not sure if you still want to partition by call_date in this case (I removed it). Change the PARTITION BY part if needed.
;WITH tmp AS
(
SELECT *, ROW_NUMBER()
OVER
(PARTITION BY to_tel, duration
ORDER BY rates_start DESC) as rn
FROM ##TempTable
WHERE call_date < #somedate
)
SELECT *
FROM tmp
WHERE rn = 1
ORDER BY customer_id, to_code, duration

Related

Union query removing blank rows

I'm trying to union two different results but I'm not sure how to remove the blank values. The paid_date and check_date are sometimes different. What do I need to do to modify the code? I've tried doing MAX but didn't seem to work. Thanks.
Results:
What I want:
WITH PAID AS
(
SELECT PIDATE
,SUM(PAY) AS PAID
,ROW_NUMBER() OVER(ORDER BY PAYDATE DESC) AS ROW_NUM
FROM CLAIM
WHERE PAY<>0
GROUP BY PAYDATE
)
,TOTAL_PAID AS
(
SELECT CONVERT(DATE,CONVERT(VARCHAR(10),PAYDATE)) AS PAID_DATE
,FORMAT(PAID,'C','EN-US') AS PAID
FROM PAID
WHERE ROW_NUM <= 10
)
,CHECKS AS
(
SELECT DISTINCT CHECK_DATE
,SUM(PAYMENT) AS PAYMENT
,ROW_NUMBER() OVER(ORDER BY CHECK_DATE DESC) AS ROW_NUM
FROM CR
GROUP BY CHECK_DATE
)
,TOTAL_CHECKS AS
(
SELECT CONVERT(DATE,CONVERT(VARCHAR(10),CHECK_DATE)) AS CHECK_DATE
,FORMAT(PAYMENT,'C','EN-US') AS PAYMENT
FROM CHECKS
WHERE ROW_NUM <= 10
)
,FINAL AS
(
SELECT PAID_DATE
,PAID
,'' AS CHECK_DATE
,'' AS PAYMENT
FROM TOTAL_PAID
UNION ALL
SELECT '' AS PAID_DATE
,'' AS PAID
,CHECK_DATE
,PAYMENT
FROM TOTAL_CHECKS
)
SELECT *
FROM FINAL
In this scenario, you must not use union. you must use join instead.
Try join two sequence on paid_date = check_date and select proper field from each set.

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

SQL LAG Days since last order

Hi I am trying to create a windowed query in SQL that shows me the days since last order for each customer.
It now shows me the days in between each order.
What do I need to change in my query to have it only show the days since the last and the previous order per customer? Now it shows it for every order the customer made.
Query:
SELECT klantnr,besteldatum,
DATEDIFF(DAY,LAG(besteldatum) OVER(PARTITION BY klantnr ORDER BY besteldatum),besteldatum) AS DaysSinceLastOrder
FROM bestelling
GROUP BY klantnr,besteldatum;
You can use row_number() to order the rows by besteldatum for each klantnr, and return the latest two using a derived table (subquery) or common table expression.
derived table version:
select klantnr, besteldatum, DaysSinceLastOrder
from (
select klantnr, besteldatum
, DaysSinceLastOrder = datediff(day,lag(besteldatum) over (partition by klantnr order by besteldatum),besteldatum)
, rn = row_number() over (partition by klantnr order by besteldatum desc)
from bestelling
group by klantnr, besteldatum
) t
where rn = 1
common table expression version:
;with cte as (
select klantnr, besteldatum
, DaysSinceLastOrder = datediff(day,lag(besteldatum) over (partition by klantnr order by besteldatum),besteldatum)
, rn = row_number() over (partition by klantnr order by besteldatum desc)
from bestelling
group by klantnr, besteldatum
)
select klantnr, besteldatum, DaysSinceLastOrder
from cte
where rn = 1
If you want one row per customer, rn = 1 is the proper filter. If you want n number of latest rows, use rn < n+1.

CASE when statement SQL Server

I have a stored procedure in the works, however, I'm missing a few pieces of data when I run it. I know the reason why, but I'm having a hard time figure it out... this is my code:
INSERT INTO tempIntake (Pop, PlanID, PopFull, ApptDate, [1stAppt], Followup, Rn, UserID)
SELECT Pop, PlanID, PopFull, InterviewDate, 1 stAppt, Followup, rn, #UserID
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY PlanID ORDER BY AddedDate ASC) AS rn
FROM VInfo
WHERE AddedDate IS NOT NULL
) t
WHERE rn = 1 AND interviewdate >= #fromDate AND interviewDate <= #toDate
So what I'm trying to do here is this....For some PLANID's I don't have an added date. Because I'm filtering by the AddedDate and in case is null - this data does not come up - even though I need it to be shown. In this case I'd like to make it a dummy date like '1/1/2016' this way, when the actually AddedDate becomes available in the table, it will be used instead of the dummy date.
If AddedDate can't be "bigger" then GETDATE(), you can use ISNULL(AddedDate,GETDATE())) and remove the where AddedDate is not null condition:
Insert into tempIntake(Pop, PlanID, PopFull, ApptDate, 1stAppt, Followup, Rn, UserID)
select
Pop, PlanID, PopFull, InterviewDate, 1stAppt, Followup, rn, #UserID
from
(Select
*,
row_number() over (partition by PlanID order BY ISNULL(AddedDate,GETDATE())) as rn
from
VInfo) t
where
rn = 1
and interviewdate >= #fromDate
and interviewDate <= #toDate

Select the lowest n values from a group

This is kind of like this questions:
T-SQL: How to use MIN
But I want it to return the lowest 4 values per group.
Thank you
Use a CTE with ROW_NUMBER:
WITH CTE AS(
SELECT T.*, RN=ROW_NUMBER()OVER(PARTITION BY Col1 Order By Col2 ASC)
FROM dbo.TableName T
)
SELECT * FROM CTE WHERE RN <= 4
Ranking Functions
SELECT
ID, SomeVal
FROM (
SELECT ID, SomeVal, row_number() over(PARTITION BY id ORDER BY SomeVal ASC) rn
FROM [TableName]
) T
WHERE rn <= 4
This gives you the lowest first 4 SomeVal values per ID.

Resources