How to loop in Select Query SQL - sql

Hi I have this Table like this
ICN StartContract EndContract ContractValue PeriodOfContract
A 2019-12-31 17:00:00.000 2020-03-30 17:00:00.000 19546194.00 3.00
B 2019-12-31 17:00:00.000 2020-12-30 17:00:00.000 1397095800.00 12.00
C 2021-02-28 17:00:00.000 2022-02-27 17:00:00.000 4016244584.00 12.00
D 2018-05-27 17:00:00.000 2021-05-30 17:00:00.000 9686992857.00 36.00
I want to create a view to loop a Period of Contract and create a new row in My View. Example Result
ICN Date Amount
A 2019-12-31 6,515,398
A 2020-01-31 6,515,398
A 2020-02-29 6,515,398
I've seen some loop examples but mostly it's used only on the function. I want to loop the period of the contract and populate a new row based on the period on my View.
This is My Query
/****** Script for SelectTopNRows command from SSMS ******/
SELECT
ICN, StartContract , EndContract, ContractValue, PeriodOfContract
FROM [FactProject]
Any suggestion or example query to do that? Thanks

;WITH n(n) AS
(
SELECT 0
UNION ALL
SELECT n+1 FROM n WHERE n+1 < 100
)
SELECT ICN, C.[Date], C.Amount FROM T
CROSS APPLY
(
SELECT
CAST(DATEADD(MONTH, n, StartContract) AS date) [Date],
CAST(ROUND(ContractValue / PeriodOfContract, 0) AS int) Amount
FROM n
WHERE
n.n < T.PeriodOfContract
) C
ORDER BY ICN, [Date]
I used WITH n(n) to generate a list of int numbers (explained here). Note: You should increase the number 100 if you may have a PeriodOfContract value more than 100.
Output:
ICN Date Amount
A 2019-12-31 6515398
A 2020-01-31 6515398
A 2020-02-29 6515398
B 2019-12-31 116424650
B 2020-01-31 116424650
...

Related

How to break datetime in 12 hour chunks and use it for aggregation in Presto SQL?

I have been trying to break the datetime in 12 hour chunk in Presto SQL but was unsuccessful.
Raw data table:
datetime
Login
2022-05-08 07:10:00.000
1234
2022-05-09 23:20:00.000
5678
2022-05-09 06:20:00.000
5674
2022-05-08 09:20:00.000
8971
The output table should look like below. I have to get count of login in 12 hour chunks. So, first should be from 00:00:00.000 to 11:59:00:000 and the next chunk from 12:00:00.000 to 23:59:00:000
Output:
datetime
count
2022-05-08 00:00:00.000
2
2022-05-08 12:00:00.000
0
2022-05-09 00:00:00.000
1
2022-05-09 12:20:00.000
1
This should work:
Extract the hour from the timestamp, then integer divide it by 12. That will make it 0 till 11:59, and 1 till 23:59. Then, multiply that back by 12.
Use that resulting integer to DATE_ADD() it with unit 'HOUR' to the timestamp of the row truncated to the day.
SELECT
DATE_ADD('HOUR',(HOUR(ts) / 12) * 12, TRUNC(ts,'DAY')) AS halfday
, SUM(login) AS count_login
FROM indata
GROUP BY
halfday
;
-- out halfday | count_login
-- out ---------------------+-------------
-- out 2022-05-08 00:00:00 | 15879
-- out 2022-05-08 12:00:00 | 5678
This query worked for me.
SELECT
DATE_ADD('HOUR',(HOUR(ts) / 12) * 12, date_trunc('DAY',ts)) AS halfday
, SUM(login) AS count_login
FROM indata
GROUP BY
halfday
;

SQL - Count total IDs each day between dates

Here is what my data looks like
ID StartDate EndDate
1 1/1/2019 1/15/2019
2 1/10/2019 1/11/2019
3 2/5/2020 3/10/2020
4 3/10/2019 3/19/2019
5 5/1/2020 5/4/2020
I am trying to get a list of every date in my data set,and how many IDs fall in that time range, aggregated to the date level. So for ID-1, it would be in the records for 1/1/2019, 1/2/2019...through 1/15/2019.
I am not sure how to do this. All help is appreciated.
If you don't have a calendar table (highly recommended), you can perform this task with an ad-hoc tally table in concert with a CROSS APPLY
Example
Declare #YourTable Table ([ID] varchar(50),[StartDate] date,[EndDate] date)
Insert Into #YourTable Values
(1,'1/1/2019','1/15/2019')
,(2,'1/10/2019','1/11/2019')
,(3,'2/5/2020','3/10/2020')
,(4,'3/10/2019','3/19/2019')
,(5,'5/1/2020','5/4/2020')
Select A.ID
,B.Date
From #YourTable A
Cross Apply (
Select Top (DateDiff(DAY,A.[StartDate],A.[EndDate])+1) Date=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),A.[StartDate])
From master..spt_values n1,master..spt_values n2
) B
Returns
ID Date
1 2019-01-01
1 2019-01-02
1 2019-01-03
1 2019-01-04
1 2019-01-05
1 2019-01-06
1 2019-01-07
1 2019-01-08
1 2019-01-09
1 2019-01-15
2 2019-01-10
2 2019-01-11
....
5 2020-05-01
5 2020-05-02
5 2020-05-03
5 2020-05-04

Merge two records date if ToDate equal second FromDate SQL Server?

Example data:
FK_EmployeeId FromDate ToDate DateDiff
20325 2016-06-24 00:00:00.000 2016-06-25 00:00:00.000 2
20325 2016-06-25 00:00:00.000 2016-06-26 00:00:00.000 2
20325 2016-06-26 00:00:00.000 2016-06-28 00:00:00.000 3
20325 2016-06-28 00:00:00.000 2016-06-29 00:00:00.000 2
20325 2016-06-29 00:00:00.000 2016-06-30 00:00:00.000 2
20325 2016-06-30 00:00:00.000 2016-07-01 00:00:00.000 2
20325 2016-07-01 00:00:00.000 2016-07-02 00:00:00.000 2
20325 2016-07-02 00:00:00.000 2016-07-03 00:00:00.000 2
20325 2016-07-03 00:00:00.000 2016-07-04 00:00:00.000 2
20325 2016-07-04 00:00:00.000 2016-07-05 00:00:00.000 2
And I would like to get the following output:
FK_EmployeeId FromDate ToDate DateDiff
20325 2016-06-24 00:00:00.000 2016-06-26 00:00:00.000 3
20325 2016-06-28 00:00:00.000 2016-07-05 00:00:00.000 8
I think you are trying to do something like the below using a windowing function to join the records to themselves to perform the date comparisons across 2 rows.
However as people have already suggested in the comments your sample data above contains all sequential dates so its not really clear how your expecting this to work. I've therefore excluded a middle value in the sample data to demonstrate the approach.
--TABLE JUST FOR EXAMPLE QUERY
DECLARE #SomeTable TABLE ([FK_EmployeeId] INT,[FromDate] DATETIME,[ToDate] DATETIME,[DateDiff] INT)
--YOUR SAMPLE DATA
INSERT INTO #SomeTable
([FK_EmployeeId],[FromDate],[ToDate],[DateDiff])
SELECT 20325,'2016-06-24 00:00:00.000','2016-06-25 00:00:00.000',2
UNION SELECT 20325,'2016-06-25 00:00:00.000','2016-06-26 00:00:00.000',2
UNION SELECT 20325,'2016-06-26 00:00:00.000','2016-06-28 00:00:00.000',3
UNION SELECT 20325,'2016-06-28 00:00:00.000','2016-06-29 00:00:00.000',2
UNION SELECT 20325,'2016-06-29 00:00:00.000','2016-06-30 00:00:00.000',2
--UNION SELECT 20325,'2016-06-30 00:00:00.000','2016-07-01 00:00:00.000',2 --<<
UNION SELECT 20325,'2016-07-01 00:00:00.000','2016-07-02 00:00:00.000',2
UNION SELECT 20325,'2016-07-02 00:00:00.000','2016-07-03 00:00:00.000',2
UNION SELECT 20325,'2016-07-03 00:00:00.000','2016-07-04 00:00:00.000',2
UNION SELECT 20325,'2016-07-04 00:00:00.000','2016-07-05 00:00:00.000',2
--THE POINT:
;WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY [FK_EmployeeId] ORDER BY [ToDate]) AS 'RowNo'
FROM
#SomeTable
)
SELECT
a.*,
DATEDIFF(DAY,a.[FromDate],b.[ToDate]) AS 'NewDiff'
FROM
cte a
JOIN cte b
ON a.[RowNo] + 1 = b.[RowNo]
WHERE
a.[ToDate] <> b.[FromDate]
A little more detail in the question next time please.

SQL previous value

I've created a SQL statement:
SELECT
ROW_NUMBER() OVER (ORDER BY Q2.FUNCTIONAL_LOCATION) AS Rowy,
Q1.FACT_MEASUREMENT_KEY,
CONVERT(VARCHAR,Q1.Doc_Time,102) AS TIME
FROM
dbo.DIM_PROJECT_TECH_OBJ Q2
INNER JOIN
dbo.FACT_MEASUREMENT Q1 ON (Q1.PROJECT_TECH_OBJ_KEY = Q2.PROJECT_TECH_OBJ_KEY)
WHERE
Q1.Measurement_Position = 'XXX'
Getting this result:
1 16124 08:00:00
2 53969 12:30:00
3 54282 17:15:00
4 55231 18:00:00
5 56196 15:00:00
6 16123 08:00:00
7 55393 12:30:00
8 55423 09:30:00
9 54283 08:00:00
My goal is to obtain the "Record-1" TIME in each row (expecting an error for the first one), like this:
1 16124 8:00:00
2 53969 12:30:00 8:00:00
3 54282 17:15:00 12:30:00
4 55231 18:00:00 17:15:00
5 56196 15:00:00 18:00:00
6 16123 8:00:00 15:00:00
7 55393 12:30:00 8:00:00
8 55423 9:30:00 12:30:00
9 54283 8:00:00 9:30:00
I've already failed trying to use:
ROW_NUMBER() OVER (PARTITION BY Q1.FACT_MEASUREMENT_KEY ORDER BY Q1.FACT_MEASUREMENT_KEY ) AS RowP
But I got error code 102.
This version of SQL Server does not support LAG statements.
Thanks in advance for any suggestion/help.
Regs
You can do this with a self join on the results of your query:
WITH t as (
SELECT ROW_NUMBER() OVER (ORDER BY Q2.FUNCTIONAL_LOCATION) AS Rowy,
Q1.FACT_MEASUREMENT_KEY,
CONVERT(VARCHAR(255), Q1.Doc_Time, 102) AS TIME
FROM dbo.DIM_PROJECT_TECH_OBJ Q2 INNER JOIN
dbo.FACT_MEASUREMENT Q1
ON Q1.PROJECT_TECH_OBJ_KEY = Q2.PROJECT_TECH_OBJ_KEY
WHERE Q1.Measurement_Position = 'XXX'
)
select t.*, tprev.time
from t left join
t tprev
on tprev.rowy = t.rowy - 1;
When you upgrade to SQL Server 2012+, you can replace this with lag().
Also, when you use varchar() (and related types in SQL Server), always use a length. SQL Server has different default lengths in different contexts -- and the default might not be good enough in some cases.

Why the Lookup function in SSRS is failing

I have two tables in my database as follows:
SELECT TOP 12 [Date], [Amount]
FROM [Db].[dbo].[final]
UNION
SELECT MAX([F1]) 'Date', SUM([F2]) 'Amount' FROM (
SELECT TOP 5 [F1], [F2]
FROM [Db].[dbo].[origtable]
WHERE [F1] IS NOT NULL
ORDER BY [F1] DESC
) c
SELECT TOP 12 [date_period2] AS [Date], [trnchargeamt] AS [Amount]
FROM [Db].[dbo].[othertable]
ORDER BY [date_period2] DESC
Which displays the following (first query is the top and second query is the bottom):
Date Amount
2013-07-31 00:00:00.000 9658254
2013-08-31 00:00:00.000 6659659
2013-09-30 00:00:00.000 14256326
2013-10-31 00:00:00.000 8912215
2013-11-30 00:00:00.000 9326659
2013-12-31 00:00:00.000 10211985
2014-01-31 00:00:00.000 8652365
2014-02-28 00:00:00.000 16256326
2014-03-31 00:00:00.000 24454342
2014-04-30 00:00:00.000 16345908
2014-05-30 00:00:00.000 6976515.77
2014-05-30 00:00:00.000 23578640
Date Amount
201406 42492.78
201405 1846703.374
201405 44390961.65
201404 45413273.91
201403 46943807.39
201402 33744223.24
201401 41630266.94
201312 40672523.92
201311 42465408.47
201310 47878730.59
201309 39444986.25
201308 40554376.28
In my SSRS I have it like the following way to display the charts:
I am using the following lookup function to display the first table with the second table:
=Lookup(Fields!Date.Value,Fields!Date.Value, Fields!Amount.Value, "WMGDailyPaymentsRed")
I get the following warning and nothing is displayed for the second chart:
[rsRuntimeErrorInExpression] The Y expression for the chart ‘Chart8’ contains an error:
Exception of type 'Microsoft.ReportingServices.ReportProcessing.ReportProcessingException_ComparisonError' was thrown.`
As you can see from the results of your select statement the first SQL.. has an actual Date and the second sql has a date period with just year and month.. hence comparing both would not work. You would need to modify your first query to format the date into YYYYMM format and then it would work in the lookup.