I have a table that contains Customers,Anchor Date(original sales date),Call Frequency(7,14 or 21 days). I need to use the customers specific Anchor date and Frequency to create and add future call records to a table until a defined end date. I am using SQL 2008
This looks like a start:
declare #Customers as Table ( CustomerId Int Identity, AnchorDate Date, CallFrequency Int );
insert into #Customers ( AnchorDate, CallFrequency ) values
( '20130101', 7 ), ( '20130102', 14 ), ( '20130103', 21 ),
( '20130104', 7 ), ( '20130105', 14 ), ( '20130106', 21 ),
( '20130107', 7 ), ( '20130108', 14 ), ( '20130109', 21 );
select *
from #Customers
declare #EndDate as Date = '20131231';
declare #Today as Date = SysDateTime();
with FutureCalls as (
select CustomerId, DateAdd( day, ( DateDiff( day, AnchorDate, #Today ) / CallFrequency + 1 ) * CallFrequency, AnchorDate ) as CallDate, CallFrequency
from #Customers
union all
select CustomerId, DateAdd( day, CallFrequency, CallDate ), CallFrequency
from FutureCalls
where DateAdd( day, CallFrequency, CallDate ) <= #EndDate
)
select *
from FutureCalls
order by CallDate, CustomerId
option ( MaxRecursion 0 )
Related
Looking at other posts was not working due to my lack of ability .
I am trying to extract a Cohort from the date of installation .
information TABLE
u_status
used : created_at , last_login
u_daily_login
SQL
SET
#targetDate = '2020-07-01';
SELECT
#Datecount := TIMESTAMPDIFF(
DAY,
#targetDate,
DATE_FORMAT(NOW(), '%Y-%m-%d')) -1;
SELECT
dl.df,
COUNT(udl.uMasterId)
FROM
(
SELECT
DATE_FORMAT(
DATE_ADD(
#targetDate,
INTERVAL td.generate_series DAY
),
'%Y-%m-%d'
) AS df
FROM
(
SELECT
0 generate_series
FROM DUAL
WHERE
(#num := 1 -2) * 0
UNION ALL
SELECT
#num := #num +1
FROM
`information_schema`.COLUMNS
WHERE
#num <= #Datecount
) AS td
) AS dl
LEFT JOIN(
SELECT udlt.*
FROM
(
SELECT
*
FROM
u_daily_login
WHERE
DATE >= #targetDate
) AS udlt
INNER JOIN(
/*基準日に登録したユニークユーザー*/ SELECT
*
FROM
(
SELECT
DATE_FORMAT(us.`createdAt`, '%Y-%m-%d') AS cdate,
us.name,
uMasterId
FROM
u_status AS us
WHERE
DATE_FORMAT(us.`createdAt`, '%Y-%m-%d') = #targetDate
) AS noise
GROUP BY
noise.name
) AS uus
ON
uus.uMasterId = udlt.uMasterId
) AS udl
ON
dl.df = udl.date
GROUP BY
dl.df
LIMIT 100;
I got the desired result, As it is now, I'm typing targetDate manually.
ex. #targetDate = 2020-07-02 , "targetDate = 2020-07-03 ...etc
How can I efficiently extract daily cohorts?
I am new to this and i am wondering how to input data into SSRS table and auto generate for the subsequent months. This is the format of the table.
Appreciated for any help given.
You can generate a date range using the following SQL
DECLARE #date_start AS DATETIME
SET #date_start = '01-DEC-2017'
;WITH
finalvalues
AS
(
SELECT tbl.* FROM (VALUES
( '01-Dec-2017', 6414.6563, 429.6846, -1390.8474)
, ( '02-Dec-2017', 6476.6563, 432.751, -1312.4928)
, ( '03-Dec-2017', 6538.6563, 435.8174, -1234.1382)
, ( '04-Dec-2017', 6600.6563, 438.8838, -1155.7836)
, ( '05-Dec-2017', 6662.6563, 441.9502, -1077.429)
, ( '06-Dec-2017', 6724.6563, 445.0166, -999.074399999999)
, ( '07-Dec-2017', 6786.6563, 448.083, -920.719799999999)
, ( '08-Dec-2017', 6848.6563, 451.1494, -842.365199999999)
, ( '09-Dec-2017', 6910.6563, 454.2158, -764.010599999999)
, ( '10-Dec-2017', 6972.6563, 457.2822, -685.655999999999)
, ( '11-Dec-2017', 7034.6563, 460.3486, -607.301399999999)
, ( '12-Dec-2017', 7096.6563, 463.415, -528.946799999999)
, ( '13-Dec-2017', 7158.6563, 466.4814, -450.592199999999)
, ( '14-Dec-2017', 7220.6563, 469.5478, -372.2376)
, ( '15-Dec-2017', 7282.6563, 472.6142, -293.883)
, ( '16-Dec-2017', 7344.6563, 475.6806, -215.5284)
) tbl ([Date], [IncLoad], [ITLoad], [RH])
)
,
manufactured_dates
AS
(
SELECT
day_date = DATEADD(day, dte.[number], #date_start)
FROM
master.dbo.spt_values AS dte
WHERE
1=1 -- <-- used in testing to be able to comment out other clauses below
AND dte.[type] = 'P'
AND dte.[number] <= 365 -- <-- filter how many rows you want to see here
)
SELECT
'Date' = md.[day_date]
, 'IncLoad' = AVG(incload)
, 'ITLoad' = AVG(ITLoad)
FROM
finalvalues AS fv
FULL OUTER JOIN manufactured_dates AS md ON md.[day_date] = fv.[Date]
GROUP BY
md.[day_date]
I have table like this:
table's name: registrationdate
I want to get the maximum value on last_update's column, so I use this query:
SELECT idtemp, max(last_update) FROM `registrationdate`
then the result will be like this:
and I have table like this:
table's name: temp
then I want to compare max(last_update) in registrationdate's table and generatedtime in temp's table
this is the schema:
what may I do so that I can get table like that? Thanks in advance.
Fyi, idtemp in registrationdate's table = id in temp's table
Please try the following...
SELECT ID AS ID,
generatedTime AS generatedTime,
tempTable AS tempTable,
CASE
WHEN generatedTime < maxLastUpdate THEN
'not'
ELSE
'update'
END AS UPDATEorNot
FROM temp
JOIN ( SELECT idtemp AS idtemp,
MAX( last_update ) AS maxLastUpdate
FROM registrationdate
GROUP BY idtemp
) AS maxLastUpdateFinder ON temp.ID = maxLastUpdateFinder.idtemp;
Assumptions
That records in temp that do not have at least one matching record in registrationdate do not need to be included in the output.
That the comparison and sample data are valid and the sample output's UPDATEorNot field should read not.
Explanation
This statement starts with a subquery that finds each unique value of idtemp in registrationdate and the most recent value of last_update associated with it.
An INNER JOIN is then performed between temp and the results of the subquery so that each record in temp with at least one corresponding record in registrationdate is retained and has its corresponding most recent value of last_update appended to it.
The fields from temp are then SELECTed, and a CASE statement used to determine the value to be selected for each record's UPDATEorNot field.
Please note that my statement will return not when the comparison that you supplied is applied to the sample data. If you want update to be chosen then you will need to change your comparison from generatedTime < max( last_update ) to generatedTime > max( last_update ), or to correct your sample data.
Testing
My statement was tested against a sample database created using the following script...
CREATE TABLE registrationdate
(
last_update DATETIME,
idtemp INT
);
INSERT INTO registrationdate ( last_update,
idtemp )
VALUES ( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 ),
( '2017-05-12 14:20:58', 0 );
CREATE TABLE temp
(
ID INT,
generatedTime DATETIME,
tempTable VARCHAR( 50 )
);
INSERT INTO temp ( ID,
generatedTime,
tempTable )
VALUES ( 0, '2017-05-01 14:37:00', 'temp_pelamardoktorjk' ),
( 2, '2017-05-01 14:37:00', 'temp_pelamarmagisteripk' ),
( 3, '2017-05-01 14:38:00', 'temp_pelamarmagisterstatusinstitusi' ),
( 4, '2017-05-01 14:38:00', 'temp_pelamarmagisterusia' ),
( 5, '2017-05-01 14:38:00', 'temp_pelamarmagisterstatusinstansi' );
If you have any questions or comments, then please feel free to post a Comment accordingly.
Appendix 1
The following is an alternative form of the above statement...
SELECT ID AS ID,
generatedTime AS generatedTime,
tempTable AS tempTable,
CASE
WHEN generatedTime < MAX( last_update ) THEN
'not'
ELSE
'update'
END AS UPDATEorNot
FROM temp
JOIN registrationdate ON temp.ID = registrationdate.idtemp
GROUP BY ID,
generatedTime,
tempTable;
Appendix 2
Please try the following attempted rewrite of the linked to code...
SELECT
generatedTime AS generatedTime,
tempTable AS tempTable,
CASE
WHEN ( ( generatedTime < ( SELECT MAX( last_update ) AS maxPelamarmhsdoktor
FROM pelamarmhsdoktor ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxAkdmstmayor
FROM akdmst_mayor ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxIpbmstdepartemen
FROM ipbmst_departemen ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxIpbmstfakultas
FROM ipbmst_fakultas ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxIpbrefjeniskelamin
FROM ipbref_jeniskelamin ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxJenisinstansi
FROM jenisinstansi ) ) OR
( generatedTime < ( SELECT MAX( last_update ) AS maxJenisinstitusi
FROM jenisinstitusi
) ) ) THEN
'Yes'
ELSE
'No'
END AS NeedsToUpdateOrNot
FROM generatedTime;
Let suppose i have these fields in my table Year, Month, Customer,Market,Product,Production Place, Category and Sales(decimal). Now I want an addition column Rolling 12 Sales which calculates sum of sales for current month + past 11 month.
rolling 12 sales (feb 2014)= sales (march 2013)+ sales (april 2013)+..........+sale (Feb 2014)
We have already achieved it using Co-related Sub query with AND condition for all the dimension, but that doesn't provides right out put!
Co-related sub=query works when i have only 4 colum like year, month , customer and sales
Please help!
Regards
Sushant
I'm going to assume that if your table's columns are
Year, Month, Customer,Market,Product,Production Place, Category and Sales(decimal)
... you want your Rolling 12 Sales column to be only the last 12 months' sales for that customer, market, product, production place, and category, rather than summarized to some higher level.
You don't say whether any of these columns can be Null, but I'm going to assume they can't, for simplicity.
I would expect this to work (given the conditions I mention above):
Select Year
, Month
, Customer
, Market
, Product
, [Production Place]
, Category
, Sales
, [Rolling 12 Month] =
(Select SUM(t2.Sales)
From Table1 t2
Where t1.Customer = t2.Customer
and t1.Market = t2.Market
and t1.Product = t2.Product
and T1.[Production Place] = t2.[Production Place]
and t1.Category = t2.Category
and (
(t2.Year = t1.Year and t2.Month <= t1.Month)
OR (t2.Year = t1.Year - 1 and t2.Month > t1.Month)
)
)
From Table1 t1
If any of those columns in the subquery's WHERE clause are nullable, change their format to this:
Where ((t1.Market = t2.Market) or (t1.Market IS NULL and t2.Market IS NULL))
If this doesn't work, please explain what error message or incorrect data you get. Thanks.
ETA: You asked whether this could be made to work in a stored procedure. I don't see why it couldn't. You didn't say what the parameters of the stored procedure needed to be (Customer? Current Year and Month?) so the version below has no parameters and returns data for all products and customers that had activity for the last twelve months.
Create dbo.Procedure1()
AS
Begin
declare #CurrentMonth int
, #CurrentYear int
-- If you want to parameterize this, you could make #CurrentMonth and #CurrentYear parameters
-- and skip this.
set #currentMonth = DatePart(MM, GetDate())
set #CurrentYear = DatePart(YYYY,GetDate())
;
with SalesFor12Months
as (
select Year
, Month
, Customer
, Market
, Product
, [Production Place]
, Category
, Sales
from Table1 t1
where (#CurrentYear = T1.Year and #CurrentMonth >= t1.Month)
OR (#CurrentYear - 1 = t1.Year and #CurrentMonth < t1.Month)
)
, SalesForCurrentMonth
as (
select *
from Table1
where Month = #CurrentMonth
and Year = #CurrentYear
)
, AllCustomers
as (
select distinct
Customer
, Market
, Product
, [Production Place]
, Category
from SalesFor12Months
)
select Month = #CurrentMonth
, Year = #CurrentYear
, ac.Customer
, ac.Market
, ac.Product
, ac.[Production Place]
, ac.Category
, Sales = COALESCE(curSales.Sales,0)
, [Rolling 12 Month] = COALESCE(
(Select SUM(t2.Sales)
From SalesFor12Months t2
Where ac.Customer = t2.Customer
and ac.Market = t2.Market
and ac.Product = t2.Product
and ac.[Production Place] = t2.[Production Place]
and ac.Category = t2.Category
)
,0)
from AllCustomers ac
left join SalesForCurrentMonth curSales
on ac.Customer = curSales.Customer
and ac.Market = curSales.Market
and ac.Product = curSales.Product
and ac.[Production Place] = curSales.[Production Place]
and ac.Category = curSales.Category
End
Hope that helps. I did that without having test data so I apologize if there are typos or other errors.
Join SELECT
'PMD' as RecType,
PMID as RecID,
CustomerID,
PMMonth as Month,
PMYear as Year,
Quantity as Rolling12Packs,
Size * Quantity / 1000 AS Rolling12Litres,
(PMDelSpl.Method) as Method,
(PMDelSpl.Size) as Size,
(PMDelSpl.Shape) as Shape,
(PMDelSpl.System) as System,
(PMDelSpl.Type) as Type,
(PMDelSpl.Category) as Category,
(PMDelSpl.SubCat) as SubCat,
(PMDelSpl.Place) as Place,
PMDelSpl.Group,
PMDelSpl.Distribution,
convert( datetime, str( PMYear ) + '/' + STR( PMMonth ) + '/01' ) as Period,
L_ProductType AS LocalCategory,
L_ProductCategory AS LocalSubcategory
FROM PMDelSpl;
**For i=1 to 11**
Join SELECT
'PMD' as RecType,
PMID as RecID,
CustomerID,
Quantity as Rolling12Packs,
Size * Quantity / 1000 AS Rolling12Litres,
(PMDelSpl.Method) as Method,
(PMDelSpl.Size) as Size,
(PMDelSpl.Shape) as Shape,
(PMDelSpl.System) as System,
(PMDelSpl.Type) as Type,
(PMDelSpl.Category) as Category,
(PMDelSpl.SubCat) as SubCat,
L_ProductType AS LocalCategory,
L_ProductCategory AS LocalSubcategory,
(PMDelSpl.Place) as Place,
PMDelSpl.Group,
PMDelSpl.Distribution,
datepart( month, dateadd( month, $(i), convert( datetime, str( PMYear ) + '/' + STR( PMMonth ) + '/01' ) ) ) as Month,
datepart( year, dateadd( month, $(i), convert( datetime, str( PMYear ) + '/' + STR( PMMonth ) + '/01' ) ) ) as Year,
dateadd( month, $(i), convert( datetime, str( PMYear ) + '/' + STR( PMMonth ) + '/01' ) ) as Period
FROM PMDelSpl
WHERE dateadd( month, $(i), convert( datetime, str( PMYear ) + '/' + STR( PMMonth ) + '/01' ) ) <GETDATE();
**Next i**
SQL Server 2008.
declare #pardate table ( pardateid int, pardatewhen datetime2(3) )
insert into #pardate values ( 1 , '2011-09-17 12:43' )
insert into #pardate values ( 2 , '2011-09-17 12:44' )
insert into #pardate values ( 3 , '2011-10-11 12:45' )
insert into #pardate values ( 4 , '2011-10-12 12:46' )
insert into #pardate values ( 5 , '2011-10-13 12:47' )
insert into #pardate values ( 6 , '2011-11-20 12:48' )
insert into #pardate values ( 7 , '2011-11-21 12:49' )
insert into #pardate values ( 8 , '2011-11-22 12:50' )
declare #child table ( childid int , pardateid int , childvalue char(6) )
insert into #child values ( 1 , 1 , 'aaaaaa' )
insert into #child values ( 2 , 2 , 'bbbbbb' )
insert into #child values ( 3 , 3 , 'cccccc' )
insert into #child values ( 4 , 4 , 'dddddd' )
insert into #child values ( 5 , 5 , 'cccccc' )
insert into #child values ( 6 , 6 , 'cccccc' )
insert into #child values ( 7 , 7 , 'eeeeee' )
insert into #child values ( 8 , 8 , 'ffffff' )
select pardatewhen , childvalue , COUNT(childvalue)
from #child childtable join #pardate parenttable on childtable.pardateid=parenttable.pardateid
group by pardatewhen , childvalue
I am trying to get a count of #child.childvalue every day, every hour, so there would be 8760 rows in my result.
First pass had a loop and a CONVERT which takes ~5 minutes to run with the actual result set (this is just a sample for illustation). I did create a CTE to make a calendar temp table (using http://www.sqlpointers.com/2006/07/generating-temporary-calendar-tables.html), and thought it could be joined somehow to add "empty values" into the result set.
I need to get a result set that looks like this
date hour count
...
2011-09-17 0 0
....
2011-09-17 12 2
....
2011-10-11 12 1
How can that be done efficiently?
Thanks.
try this.
;WITH cal AS
(SELECT CAST('2011-01-01' AS DATETIME) AS cal_date
UNION ALL
SELECT DATEADD(hour,1,cal_date)
FROM cal
WHERE cal_date < '2011-12-31 23:00'
)
, par AS
(
select CAST(pardatewhen AS DATE) AS pardate, DATEPART(hh,pardatewhen) AS parhour , COUNT(childvalue) as num
from #child childtable
join #pardate parenttable on childtable.pardateid=parenttable.pardateid
group by CAST(pardatewhen AS DATE), DATEPART(hh,pardatewhen)
)
SELECT CAST(cal.cal_date AS DATE) AS [date],DATEPART(hh,cal.cal_date) AS [hour],ISNULL(par.num,0) AS [childvalue_count]
FROM cal
LEFT JOIN par
ON CAST(cal.cal_date AS DATE) = par.pardate
AND DATEPART(hh,cal.cal_date) = par.parhour
OPTION (MAXRECURSION 9999)
Something like (have childvalue in your query but not in your example result?)
select Cast(pardatewhen as Date) as [date], DatePart(hour,pardatewhen) as [hour] , childvalue , COUNT(childvalue)
from #child childtable
join #pardate parenttable on childtable.pardateid=parenttable.pardateid
group by Cast(pardatewhen as Date), DatePart(hour,pardatewhen), childvalue
Note Date type was introduced in SQL 2008