I would like to ALTER a proc so I can insert results into table. Can you please guide? thank you..
ALTER proc [dbo].[usp_CtotalPPPP]
AS
BEGIN
SELECT CID, Consumer1, Consumer2, datepart(year, getdate()) Year, 'Jan' Month, [Jan_S] Budget, [JanAct] Act, getdate()
FROM CProgramDetails
UNION
SELECT CID, Consumer1, Consumer2, datepart(year, getdate()) Year, 'Feb' Month, [FEBOCV_Spend] Budget, [FEBAct] Act, getdate()
FROM CProgramDetails
UNION
SELECT CID, Consumer1, Consumer2, date part(year, getdate()) Year, 'Mar' Month, [MarOCV_Spend] Budget, [MarAct] Act, getdate()
FROM CProgramDetails
UNION
SELECT CID, Consumer1, Consumer2, datepart(year, getdate()) Year, 'Apr' Month, [AprOCV_Spend] Budget, [AprAct] Act, getdate()
FROM CProgramDetails
INSERT INTO [dbo].[ABCD123] (---this is failing - I do not know where to add this)
End
IF [dbo].[ABCD123] already exists
INSERT INTO [dbo].[ABCD123]
Select ...
Union
Select ...
IF [dbo].[ABCD123] does NOT exist and you want to create it on-the-fly
SELECT CID
, Consumer1
, Consumer2
, datepart(year, getdate()) Year
, 'Jan' Month
, [Jan_S] Budget
, [JanAct] Act
, getdate()
INTO [dbo].[ABCD123] --<< only once in the top query
FROM CProgramDetails
UNION
SELECT ...
UNION
SELECT
Related
I have following data in a PostgreSQL table:
trial start_date end_date
1 20_12_2001 20_01_2005
The expected output is below:
trial start_date end_date Date[(start_end_date)] marker_start_end
1 20_12_2001 20_01_2005 20_12_2001 start
1 20_12_2001 20_01_2005 20_01_2005 end
Is there a way to calculate the additional two columns (Date[(start_end_date)], marker_start_end) without join, but a CASE expression
You can use a lateral join to turn two columns into two rows:
select *
from the_table t
cross join lateral (
values (t.start_date, 'start'), (t.end_date, 'end')
) as x(start_end_date, marker);
The UNION ALL solution might be faster though.
UNION ALL
select trial, start_date, end_date, start_date as date, 'start' marker_start_end from table1
union all
select trial, start_date, end_date, end_date as date, 'end' marker_start_end from table1
UNNEST with CASE
select trial, start_date, end_date,
case when a.num = 1 then start_date else end_date end date,
case when a.num = 1 then 'start' else 'end' end marker_start_end from
(
select trial, start_date, end_date,
unnest(array[1,2]) num from table1
) a
Hidden JOIN (but still join)
select
trial,
start_date,
end_date,
case when a.num = 1 then start_date else end_date end date,
marker_start_end
from table1, (values(1,'start'),(2, 'end')) a(num,marker_start_end)
Db fiddle
I am am building a Time Dimension table in PostgreSQL with DATE_ID and DATE_DESC.
My T-SQL (works perfectly) script is:
set DATEFIRST 1
;WITH DATES AS (
SELECT CAST('2019-01-01 00:00:00.000' AS datetime) AS [DATE]
UNION ALL
SELECT DATEADD(HH,1,[DATE])
FROM DATES
WHERE DATEADD(HH,1,[DATE]) <= CAST('2019-12-31' AS datetime)
)
SELECT
DATE_ID, DATE_DESC
from
(
SELECT
CONVERT(int, CONVERT(char(8), DATE, 112)) AS DATE_ID,
DATE AS DATE_DESC
FROM
DATES)a
order by 1
OPTION (MAXRECURSION 0)
At the moment Im trying to convert this code to PostgreSQL readable one and it does not work..
Here is mine at the moment:
set EXTRACT(DOW FROM TIMESTAMP '2019-01-01 00:00:00.000')+1
;WITH DATES AS (
SELECT CAST('2019-01-01 00:00:00.000' AS timestamp) AS DATE
UNION ALL
SELECT CURRENT_DATE + INTERVAL '1 hour'
FROM DATES
WHERE CURRENT_DATE + INTERVAL '1 hour' <= CAST('2019-12-31' AS timestamp)
)
SELECT DATE_ID, DATE_DESC from
(SELECT cast(to_char((DATE)::TIMESTAMP,'yyyymmddhhmiss') as BIGInt) AS DATE_ID,
DATE AS DATE_DESC
FROM
DATES)a
order by 1
OPTION (MAXRECURSION 0)
I need all the hours (24h) between 2019-01-01 and 2019-12-31 . At the moment I think OPTION (MAXRECURSION 0) and set EXTRACT(DOW FROM TIMESTAMP '2019-01-01 00:00:00.000')+1 is not working properly.
Its a problem of Recursive CTE, In Postgresql, your desired query will be like below
WITH recursive DATES AS (
SELECT CAST('2019-01-01 00:00:00.000' AS timestamp) AS date_
UNION ALL
SELECT date_ + INTERVAL '1 hour'
FROM DATES
WHERE date_ + INTERVAL '1 hour' <= CAST('2019-12-31' AS timestamp)
)
SELECT DATE_ID, DATE_DESC from
(SELECT cast(to_char((date_)::TIMESTAMP,'yyyymmddhhmiss') as BIGInt) AS DATE_ID,
date_ AS DATE_DESC
FROM
DATES)a
order by 1
DEMO
I have a table that has account number, end of month valid from and end of month valid to columns.
What I need is a table that has account number and a column that has all the end of month dates of when the account was live, inclusive of end of month valid to. The Current Table looks like this
New table will need to be like this
I have tried using a calendar table and an CTE table type query but have had no success.
Any help would be great.
This can be achieved using Using multiple comma separated CTEs in a statement
Query
with t0 (i) AS (select 0 union all select 0 union all select 0 union all select 0 union all select 0 union all select 0),
t1 (i) AS (select 0 from t0 a inner join t0 b on a.i = b.i),
n (i) AS (select row_number()over(order by i) from t1),
Account_details (Account_number,valid_from,valid_to,mth,Live_date)As(
select Account_number,valid_from,valid_to, datediff(month,valid_from,valid_to ) mth, valid_from"Live_date"
from tbl1
union all
select Account_number,valid_from,valid_to, datediff(month,valid_from,valid_to ) mth, EOMONTH (dateadd(month,n.i,valid_from)) "Live_date"
from tbl1
inner join n on 1=1 and n.i between 1 and datediff(month,valid_from,valid_to )
)
select *
from Account_details
where Account_details.Account_number =1
order by Account_details.Account_number
Output
CTE Table t0, t1 and n will generate numbers. This is a best way to generate rows without any data.
Then the CTE table Account_details is used to pull data from the table.
Based on sql on the msdn thread how to get month end date between two dates.
DECLARE #Old AS Table (AccountNumber INT, ValidFrom DATE, ValidTo DATE)
DECLARE #New AS Table (AccountNumber INT, LiveDate DATE)
INSERT INTO #old
SELECT 1, '20130630', '20131130' UNION ALL
SELECT 2, '20130630', '20131231' UNION ALL
SELECT 3, '20120430', '20120531' UNION ALL
SELECT 4, '20170331', '20171130'
SELECT TOP 100 * FROM #old
DECLARE #AccountNumber INT, #ValidFrom DATE, #ValidTo DATE
DECLARE #Cursor CURSOR
SET #Cursor = CURSOR FOR
SELECT AccountNumber, ValidFrom, ValidTo
FROM #old
OPEN #Cursor
FETCH NEXT INTO #Cursor FROM #AccountNumber, #ValidFrom, #ValidTo
WHILE ##FETCH_STATUS = 0
BEGIN
;WITH cteEndMonthDates (MonthEndDate)
AS
(
SELECT eomonth(#ValidFrom) AS MonthEndDate
UNION ALL
SELECT eomonth( dateadd(day, 1, MonthEndDate)) AS MonthEndDate
FROM cteEndMonthDates
WHERE MonthEndDate < eomonth(#ValidTo)
)
INSERT INTO #new (AccountNumber, LiveDate)
SELECT #AccountNumber, MonthEndDate
FROM cteEndMonthDates
FETCH NEXT FROM #Cursor INTO #AccountNumber, #ValidFrom, #ValidTo
END
CLOSE #Cursor
DEALLOCATE #Cursor
SELECT * FROM #New
Edit: Or without the cursor
DECLARE #Old AS Table (AccountNumber INT, ValidFrom DATE, ValidTo DATE)
DECLARE #New AS Table (AccountNumber INT, LiveDate DATE)
INSERT INTO #old
SELECT 1, '20130630', '20131130' UNION ALL
SELECT 2, '20130630', '20131231' UNION ALL
SELECT 3, '20120430', '20120531' UNION ALL
SELECT 4, '20170331', '20171130' UNION ALL
SELECT 5, '20180430', '20190131' UNION ALL
SELECT 6, '20160430', '20180531'
SELECT TOP 100 * FROM #old
;WITH cteEndMonthDates (AccountNumber, MonthEndDate)
AS
(
SELECT AccountNumber, eomonth(ValidFrom) AS MonthEndDate
FROM #Old
UNION ALL
SELECT x.AccountNumber, eomonth( dateadd(day, 1, MonthEndDate)) AS MonthEndDate
FROM cteEndMonthDates x
JOIN #Old o ON o.AccountNumber = x.AccountNumber
WHERE MonthEndDate < eomonth(ValidTo)
)
SELECT AccountNumber, MonthEndDate
FROM cteEndMonthDates
order by AccountNumber, MonthEndDate
This should work.
;WITH Span AS (
SELECT
AccountNumber,
ValidFrom AS Valid
FROM dbo.Input
UNION ALL
SELECT
AccountNumber,
DATEADD(DAY, 1, Span.Valid) AS Valid
FROM Span
WHERE DATEADD(DAY, 1, Span.Valid) <= (SELECT ValidTo FROM dbo.Input WHERE AccountNumber = Span.AccountNumber)
)
SELECT * FROM Span
ORDER BY Span.AccountNumber, Span.Valid
OPTION (MAXRECURSION 0);
Is there any way to INSERT multiple values with one from DB that unchangable?
I thought about WITH but without success:
WITH t as (SELECT date_trunc('hour', NOW()))
INSERT INTO my_table(ID, TIME) VALUES (1,t),(2,t);
No need for the CTE, just use a plain SELECT as the source for the insert:
insert into my_table (id, time)
select i, date_trunc('hour', NOW())
from generate_series(1,2) i;
If you really want the CTE, you need to select from it in the values clause:
WITH t as (
SELECT date_trunc('hour', NOW()) hour_t
)
INSERT INTO my_table(ID, TIME)
VALUES
(1, (select hour_t from t)),
(2, (select hour_t from t));
I have this table called Table1 as follows:
UserID Date
1 01/01/09
1 14/01/09
1 25/01/09
1 01/02/09
1 15/02/09
2 02/02/09
2 15/02/09
I am trying to return a result that counts the number of times between the MIN(Date) and 30 days after the MIN(Date) which is DATEADD(day,30,MIN(DATE)). So it would look something like this:
UserID Count
1 3
2 2
This code below is wrong but it expresses what I am trying to achieve:
SELECT COUNT(1) AS Count
FROM Table1
GROUP BY UserID
WHERE Date BETWEEN MIN(Date) AND DATEADD(day,30,MIN(DATE))
SELECT a.UserID, COUNT(a.UserID) AS [Count]
FROM Table1 AS a
INNER JOIN
(
SELECT UserID, MIN([Date]) AS MinDate
FROM Table1
GROUP BY UserID
) AS b
ON a.UserID = b.UserID
WHERE [Date] BETWEEN MinDate AND DATEADD(day, 30, MinDate)
GROUP BY a.UserID
Try this
DECLARE #table TABLE(
UserID INT,
DDate DATETIME
)
INSERT INTO #table (UserID,DDate) SELECT 1, '01 Jan 2009'
INSERT INTO #table (UserID,DDate) SELECT 1, '14 Jan 2009'
INSERT INTO #table (UserID,DDate) SELECT 1, '25 Jan 2009'
INSERT INTO #table (UserID,DDate) SELECT 1, '01 Feb 2009'
INSERT INTO #table (UserID,DDate) SELECT 1, '15 Feb 2009'
INSERT INTO #table (UserID,DDate) SELECT 2, '02 Feb 2009'
INSERT INTO #table (UserID,DDate) SELECT 2, '15 Feb 2009'
SELECT t.UserID,
COUNT(t.UserID)
FROM #table t INNER JOIN
(
SELECT UserID,
MinDate,
DATEADD(dd, 30, MinDate) MinDataAdd30
FROM (
SELECT UserID,
MIN(DDate) MinDate
FROM #table
GROUP BY UserID
) MINDates
) DateRange ON t.UserID = DateRange.UserID
WHERE t.DDate BETWEEN DateRange.MinDate AND DateRange.MinDataAdd30
GROUP BY t.UserID
I think you'll need to use a subquery to get the minimum date. I've shown it below
as a separate query into a variable as I'd probably turn this into a table-valued function.
DECLARE #STARTDATE DATETIME
SELECT #STARTDATE = MIN(DATE) FROM Table1
SELECT COUNT(1) AS Count
FROM Table1
GROUP BY UserID
WHERE Date BETWEEN #STARTDATE AND DATEADD(day,30,#STARTDATE)
I would do it like this:
select a.UserID, count(case when DDate - MinDate <= 30 then 1 end) as Count
from (
select UserID, min(DDate) MinDate
from Table1
group by UserID
) a
inner join Table1 t on a.UserID = t.UserID
group by a.UserID