Related
After running my UNION ALL query I have the same output data on the second query with equal timestamp output data. How I could gather the same output data if the area2 server has different vendors with timestamps, could the output same data be due to the order on the bottom of the query, I have tried the following query.
Current table data from both servers, AREA1 with AREA2.
QUERY
DECLARE #Invoice_Date SMALLINT;
SET #Invoice_Date = 2020;
SELECT DISTINCT 'AREA1' AS 'Server',
*
FROM (
SELECT Name,
Vendor,
Invoice_Date,
count(*) Count_InvoiceNo,
rank() OVER (
PARTITION BY Name ORDER BY count(*) DESC
) rn
FROM dbo.Invoices
WHERE Invoice_Date >= '2020-01-01'
GROUP BY Name,
Vendor,
Invoice_Date
) t
WHERE rn = 1
AND InvDate >= DATEADD(MONTH, - 12, GETDATE())
UNION ALL
SELECT DISTINCT 'AREA2' AS 'Server',
*
FROM (
SELECT Name,
Vendor,
Invoice_Date,
count(*) Count_InvoiceNo,
rank() OVER (
PARTITION BY Name ORDER BY count(*) DESC
) rn
FROM dbo.Invoices
WHERE Invoice_Date >= '2020-01-01'
GROUP BY Name,
Vendor,
Invoice_Date
) t
WHERE rn = 1
AND Invoice_Date >= DATEADD(MONTH, - 12, GETDATE())
ORDER BY SERVER,
Invoice_Date
I want to find the missing NON-consecutive dates between two consecutive date.
I am posting my SQL query and temp tables to find out the results.
But I am not getting the proper results
Here is my SQL Query
drop table #temp
create table #temp(an varchar(20),dt date)
insert into #temp
select '2133783715' , '2016-10-16' union all
select '5107537880' , '2016-10-15' union all
select '6619324250' , '2016-10-15' union all
select '7146586717' , '2016-10-15' union all
select '7472381321' , '2016-10-12' union all
select '7472381321' , '2016-10-13' union all
select '7472381321' , '2016-10-14' union all
select '7472381321' , '2016-10-24' union all
select '8186056340' , '2016-10-15' union all
select '9099457123' , '2016-10-12' union all
select '9099457123' , '2016-10-13' union all
select '9099457123' , '2016-10-14' union all
select '9099457123' , '2016-10-23' union all
select '9099457123' , '2016-11-01' union all
select '9099457123' , '2016-11-02' union all
select '9099457123' , '2016-11-03' union all
select '9165074784' , '2016-10-16'
drop table #final
SELECT an,MIN(dt) AS MinDate,MAX(dt) AS MaxDate, COUNT(*) AS ConsecutiveUsage
--DateDiff(Day,LAG(MAX(dt)) OVER (partition by an ORDER BY an),MAX(dt)) nonusageDate
into #final
FROM(
SELECT an,dt,
DATEDIFF(D, ROW_NUMBER() OVER(partition by an ORDER BY dt),dt) AS Diff
FROM #temp c
)P
GROUP BY an,diff
select * from #final order by 1
an MinDate MaxDate ConsecutiveUsage
2133783715 2016-10-16 2016-10-16 1
5107537880 2016-10-15 2016-10-15 1
6619324250 2016-10-15 2016-10-15 1
7146586717 2016-10-15 2016-10-15 1
7472381321 2016-10-12 2016-10-14 3
7472381321 2016-10-24 2016-10-24 1
7472381321 2016-10-27 2016-10-28 1
8186056340 2016-10-15 2016-10-15 1
9099457123 2016-10-12 2016-10-14 3
9099457123 2016-10-23 2016-10-23 1
9165074784 2016-10-16 2016-10-16 1
But I want results of non-usage date.
I want to get those AN which has not been used continuously since 10 days.
So here output should be like this:-
an minusagesdate maxusagedate ConsecutiveNotUseddays
7472381321 2016-10-15 2016-10-23 9
7472381321 2016-10-25 2016-10-26 2
9099457123 2016-10-15 2016-10-22 8
So I just want to find out only consecutive not used dates count and their min and max dates .
try this :
with ranked as (
select f1.*,
ROW_NUMBER() over(partition by an order by dt) rang
from #temp f1
where exists
(select * from #temp f2
where f1.an=f2.an and datediff( day, f2.dt, f1.dt) >1
)
)
select an, minusagesdate, maxusagesdate, ConsecutiveNotUseddays
from (
select f1.*,
DATEADD(DAY,1, (select f2.dt from ranked f2 where f1.an=f2.an and f2.rang+1=f1.rang)) minusagesdate ,
DATEADD(DAY,-1, f1.dt) maxusagesdate ,
datediff( day, (select f2.dt from ranked f2 where f1.an=f2.an and f2.rang+1=f1.rang), f1.dt) - 1 ConsecutiveNotUseddays
from ranked f1
) tmp
where tmp.ConsecutiveNotUseddays>0
or like this
with ranked as (
select f1.*,
ROW_NUMBER() over(partition by an order by dt) rang
from #temp f1
where exists
(select * from #temp f2
where f1.an=f2.an and datediff( day, f2.dt, f1.dt) >1
)
)
select f1.an,
DATEADD(DAY,1, f3.dtbefore) minusagesdate ,
DATEADD(DAY,-1, f1.dt) maxusagesdate ,
datediff( day, f3.dtbefore, f1.dt) - 1 ConsecutiveNotUseddays
from ranked f1
outer apply
(
select top 1 f2.dt as dtbefore from ranked f2
where f1.an=f2.an and f2.rang+1=f1.rang
) f3
where datediff( day, f3.dtbefore, f1.dt) - 1>0
It looks like you're trying to count the number of days not used between the mindate and the maxdate for each an. If that's the case, then this should do the trick:
select an, min(dt) as min_dt, max(dt) as max_dt
, count(distinct dt) as daysused --this counts each day used, but only once
, datediff(day,min(dt),max(dt)) as totaldays --this is the total number of days between min and max date
, datediff(day,min(dt),max(dt)) - count(distinct dt) as daysnotused
--This takes total days - used days to give non-used days
from #temp c
group by an
having datediff(day,min(dt),max(dt)) - count(distinct dt) >= 10
As I understood you need this:
;WITH cte AS (
SELECT an,
dt,
ROW_NUMBER() OVER (PARTITION BY an ORDER BY dt) as rn
FROM #temp
)
SELECT c1.an,
c1.dt MinDate,
c2.dt MaxDate,
DATEDIFF(day,c1.dt,c2.dt) as ConsecutiveNotUseddays
FROM cte c1
INNER JOIN cte c2
ON c1.an = c2.an AND c1.rn = c2.rn-1
WHERE DATEDIFF(day,c1.dt,c2.dt) >= 10
Output:
an MinDate MaxDate ConsecutiveNotUseddays
7472381321 2016-10-14 2016-10-24 10
For 9099457123 I got two rows with 9 in ConsecutiveNotUseddays. You can check results removing WHERE statement.
On any newer version of SQL Server this should be easy:
with x as (
select *, lag(dt) over(partition by an order by dt) dt_lag
from #temp
)
select *, datediff(day, dt_lag, dt)
from x
where datediff(day, dt_lag, dt) >= 10
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.
I think I have a tough one here... :(
I am trying to get an order count by month, even when zero. Here's the problem query:
SELECT datename(month, OrderDate) as Month, COUNT(OrderNumber) AS Orders
FROM OrderTable
WHERE OrderDate >= '2012-01-01' and OrderDate <= '2012-06-30'
GROUP BY year(OrderDate), month(OrderDate), datename(month, OrderDate)
What I'm looking to get is something like this:
Month Orders
----- ------
January 10
February 7
March 0
April 12
May 0
June 5
...but my query skips a row for March and May. I've tried COALESCE(COUNT(OrderNumber), 0) and ISNULL(COUNT(OrderNumber), 0) but I'm pretty sure the grouping is causing that not to work.
This solution doesn't require you to hard-code the list of months you might want, all you need to do is provide any start date and any end date, and it will calculate the month boundaries for you. It includes year in the output so that it will support more than 12 months and so that your start and end dates can cross a year boundary and still order correctly and show the correct month and year.
DECLARE #StartDate SMALLDATETIME, #EndDate SMALLDATETIME;
SELECT #StartDate = '20120101', #EndDate = '20120630';
;WITH d(d) AS
(
SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, #StartDate), 0))
FROM ( SELECT TOP (DATEDIFF(MONTH, #StartDate, #EndDate) + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT
[Month] = DATENAME(MONTH, d.d),
[Year] = YEAR(d.d),
OrderCount = COUNT(o.OrderNumber)
FROM d LEFT OUTER JOIN dbo.OrderTable AS o
ON o.OrderDate >= d.d
AND o.OrderDate < DATEADD(MONTH, 1, d.d)
GROUP BY d.d
ORDER BY d.d;
Since your query Just Can't guess the months you want, you will need to have the Months that you want stored in somewhere, Join them with your table, and then group.
Something like:
;With Months (Month)
AS
(
select 'January' as Month
UNION
select 'February' as Month
UNION
select 'March' as Month
UNION
select 'April' as Month
UNION
select 'May' as Month
UNION
select 'June' as Month
UNION
select 'July' as Month
UNION
select 'August' as Month
UNION
select 'September' as Month
UNION
select 'October' as Month
UNION
select 'November' as Month
UNION
select 'December' as Month
)
--Also you could have them in a "Months" Table
Then Just JOIN this table with your table:
Select
SELECT datename(month, OrderDate) as Month, COUNT(OrderNumber)
FROM Months T1
LEFT JOIN OrderTable T2 on datename(month, T2.OrderDate) = T2.Month
WHERE (T2.OrderDate >= '2012-01-01' and T2.OrderDate <= '2012-06-30')
OR T2.OrderDate IS NULL --So will show you the months with no rows
GROUP BY year(T2.OrderDate), month(T2.OrderDate), datename(month, T2.OrderDate)
Hope it works!
Here is one using recursive CTE:
declare #StartDate datetime = '2015-04-01';
declare #EndDate datetime = '2015-06-01';
-- sample data
declare #orders table (OrderNumber int, OrderDate datetime);
insert into #orders
select 11, '2015-04-02'
union all
select 12, '2015-04-03'
union all
select 13, '2015-05-03'
;
-- recursive CTE
with dates
as (
select #StartDate as reportMonth
union all
select dateadd(m, 1, reportMonth)
from dates
where reportMonth < #EndDate
)
select
reportMonth,
Count = count(o.OrderNumber)
from dates
left outer join #orders as o
on o.OrderDate >= reportMonth
and o.OrderDate < dateadd(MONTH, 1, reportMonth)
group by
reportMonth
option (maxrecursion 0);
;
I'm trying to retrieve data for a Open-high-low-close (OHLC) chart directly from the database, it's the kind of chart you see of stocks. Is this possible, and if, how?
I have a table like this (simplified):
Date | Price | PriceType
A record is created for each day, I will report per month / year, not per day as used for stocks.
I would like to query something like this:
SELECT PriceType, MAX(Price) as High, MIN(Price) as Low, [Price of first item of month] as Open, [Price of last item of month] as Close GROUP BY PriceType, Year(Date), Month(Date)
To access the SQL Server I use LLBLGen, so an anwser based on that technology would be great, a generic SQL server will do too!
It's SQL 2005, but 2008 is also an option.
Thanks.
This appears to work. There may well be a less verbose way to do it.
--create test data
CREATE TABLE #t
(priceDate DATETIME
,price MONEY
,priceType CHAR(1)
)
INSERT #t
SELECT '20090101',100,'A'
UNION SELECT '20090102',500,'A'
UNION SELECT '20090103',20 ,'A'
UNION SELECT '20090104',25 ,'A'
UNION SELECT '20090105',28 ,'A'
UNION SELECT '20090131',150,'A'
UNION SELECT '20090201',501,'A'
UNION SELECT '20090203',21 ,'A'
UNION SELECT '20090204',26 ,'A'
UNION SELECT '20090205',29 ,'A'
UNION SELECT '20090228',151,'A'
UNION SELECT '20090101',100,'B'
UNION SELECT '20090102',500,'B'
UNION SELECT '20090103',20 ,'B'
UNION SELECT '20090104',25 ,'B'
UNION SELECT '20090105',28 ,'B'
UNION SELECT '20090131',150,'B'
UNION SELECT '20090201',501,'B'
UNION SELECT '20090203',21 ,'B'
UNION SELECT '20090204',26 ,'B'
UNION SELECT '20090205',29 ,'B'
UNION SELECT '20090228',151,'B'
--query
;WITH rangeCTE
AS
(
SELECT MIN(priceDate) minDate
,MAX(priceDate) maxDate
FROM #t
)
,datelistCTE
AS
(
SELECT CAST(CONVERT(CHAR(6),minDate,112) + '01' AS DATETIME) AS monthStart
,DATEADD(mm,1,CAST(CONVERT(CHAR(6),minDate,112) + '01' AS DATETIME)) -1 AS monthEnd
,1 AS monthID
FROM rangeCTE
UNION ALL
SELECT DATEADD(mm,1,monthStart)
,DATEADD(mm,2,monthStart) - 1
,monthID + 1
FROM datelistCTE
WHERE monthStart <= (SELECT maxDate FROM rangeCTE)
)
,priceOrderCTE
AS
(
SELECT *
,ROW_NUMBER() OVER (PARTITION BY monthID, priceType
ORDER BY priceDate
) AS rn1
,ROW_NUMBER() OVER (PARTITION BY monthID, priceType
ORDER BY priceDate DESC
) AS rn2
,ROW_NUMBER() OVER (PARTITION BY monthID, priceType
ORDER BY price DESC
) AS rn3
,ROW_NUMBER() OVER (PARTITION BY monthID, priceType
ORDER BY price
) AS rn4
FROM datelistCTE AS d
JOIN #t AS t
ON t.priceDate BETWEEN d.monthStart AND d.monthEnd
WHERE monthStart <= (SELECT maxDate FROM rangeCTE)
)
SELECT o.MonthStart
,o.priceType
,o.Price AS opening
,c.price AS closing
,h.price AS high
,l.price AS low
FROM priceOrderCTE AS o
JOIN priceOrderCTE AS c
ON c.priceType = o.PriceType
AND c.monthID = o.MonthID
JOIN priceOrderCTE AS h
ON h.priceType = o.PriceType
AND h.monthID = o.MonthID
JOIN priceOrderCTE AS l
ON l.priceType = o.PriceType
AND l.monthID = o.MonthID
WHERE o.rn1 = 1
AND c.rn2 = 1
AND h.rn3 = 1
AND l.rn4 = 1
This is a little query I wrote that seems to work nicely for one time span at a time. All you need to do is comment the select DATEPARTS in order to get to the timespan you are looking for. Or you could just make multiple views for different timespans. Also the underlying data table uses Bid Ask tick style data. If you are using mids or last prices you could eliminate the case statements from the selects.
Select
tmp.num,
rf.CurveName,
rf.Period as Period,
CASE WHEN (tmp2.Bid is null or tmp2.Ask is null) then isnull(tmp2.Bid,0)+isnull(tmp2.Ask,0) else (tmp2.Bid+tmp2.Ask)/2 end as [Open],
tmp.Hi,
tmp.Lo,
CASE WHEN (rf.Bid is null or Rf.Ask is null) then isnull(rf.Bid,0)+isnull(rf.Ask,0) else (rf.Bid+rf.Ask)/2 end as [Close],
tmp.OpenDate,
tmp.CloseDate,
tmp.yr,
tmp.mth,
tmp.wk,
tmp.dy,
tmp.hr
from BidAsk rf inner join
(SELECT count(CurveName)as num,CurveName,
Period,
max(CASE WHEN (Bid is null or Ask is null) then isnull(Bid,0)+isnull(Ask,0) else (Bid+Ask)/2 end) as Hi,
min(CASE WHEN (Bid is null or Ask is null) then isnull(Bid,0)+isnull(Ask,0) else (Bid+Ask)/2 end) as Lo,
max(CurveDateTime) as CloseDate, min(CurveDateTime) as OpenDate,
DATEPART(year, CurveDateTime) As yr,
DATEPART(month, CurveDateTime) As mth,
DATEPART(week, CurveDateTime) As wk,
DATEPART(Day, CurveDateTime) as dy,
DATEPART(Hour, CurveDateTime) as hr
--DATEPART(minute, CurveDateTime) as mnt
FROM
BidAsk
GROUP BY
CurveName,Period,
DATEPART(year, CurveDateTime),
DATEPART(month, CurveDateTime),
DATEPART(week, CurveDateTime),
DATEPART(Day, CurveDateTime) ,
DATEPART(Hour, CurveDateTime)
--DATEPART(minute, CurveDateTime)
) tmp on
tmp.CurveName=rf.CurveName and
tmp.CloseDate=rf.CurveDateTime and
tmp.Period=rf.Period
inner join BidAsk tmp2 on
tmp2.CurveName=rf.CurveName and
tmp2.CurveDateTime=tmp.Opendate and
tmp2.Period=rf.Period
ORDER BY
CurveName,Period,tmp.yr,tmp.mth
--DATEPART(year, CurveDateTime),
--DATEPART(month, CurveDateTime)
--DATEPART(day, CurveDateTime),
--DATEPART(Hour, CurveDateTime),
--DATEPART(minute, CurveDateTime) )