Currently, I have an orders table that I want to extract information from. There are 4 main fields I am looking for: Order no, customer no, date1, and date 2.
Date 1 is the minimum date in the table for a specific customer number prior to the date associated with the order number within a 12 month period (that's not the order number date).
Date 2 is the minimum date in the table for a specific customer number prior to date1 within a 12 month period (that's not date 1)
Here is what I have so far but it doesn't seem to be pulling in any data. Any help is appreciated!
With CTE as
(SELECT Order_no, customer_no, MIN(order_date) AS date1
FROM dbo.orders
WHERE (order_date >= DATEADD(month, - 12, order_date)
and (order_date < DATEADD(day, - 1, order_date)))
GROUP BY Order_no, customer_no)
Select x.order_no, x.customer_no, min(x.order_date) as date2, cte.date1
from dbo.orders x
LEFT OUTER JOIN CTE ON cte.order_no=x.order_no
where x.order_date > DATEADD(month, - 12, cte.date1)
AND x.order_date < DATEADD(DAY, - 1, cte.date1)
Group by x.order_no, x.customer_no, cte.date1
You need to figure out what is filtering based on the data you have. This is more about data meaning than syntax.
Start by making sure the cte is returning any records. and then make sure by checking the data that they are th records you wanted.
With CTE as
(SELECT Order_no, customer_no, MIN(order_date) AS date1
FROM dbo.orders
WHERE (order_date >= DATEADD(month, - 12, order_date)
and (order_date < DATEADD(day, - 1, order_date)))
GROUP BY Order_no, customer_no)
select * from CTE
Once you are sure of this try with just the join
With CTE as
(SELECT Order_no, customer_no, MIN(order_date) AS date1
FROM dbo.orders
WHERE (order_date >= DATEADD(month, - 12, order_date)
and (order_date < DATEADD(day, - 1, order_date)))
GROUP BY Order_no, customer_no)
Select *
from dbo.orders x
LEFT OUTER JOIN CTE ON cte.order_no=x.order_no
Then add the where criteria back in one at a time. This is the basic technique you use when the query does not havea a syntax issue but is not returning the correct data.
Based on the comments, this is what I would try next:
SELECT Order_no, customer_no,order_date, DATEADD(month, - 12, order_date) as ordermonth, DATEADD(day, - 1, order_date) as orderday
FROM dbo.orders
This will tell you why none of your records meet the criteria.
Related
So I am trying to find count of customers who placed order both in this month and previous month. I have to find this from the beginning of last year. I came up with a query which obviously doesn't work. Can I get some help with this please?
Query:
SELECT DATE_TRUNC('month', month_column), COUNT(DISTINCT(customer_id))
FROM table
WHERE month_column >= '2021-01-01' AND customer_id IN (
SELECT customer_id
FROM table
WHERE month_column = month_column - INTERVAL '1 month')
GROUP BY 1
NOTE: month_column has only month number i.e., '2021-01-01', '2021-02-01' etc.
I am using postgresql.
This is my first stack overflow question. So, if I didn't abide by any rules, I apologize.
To make this trivial, you can use 2 queries. Get customerID's from this month (insert into temp table 1) and customerID's from last month (insert into temp table 2). Lastly just inner join both tables on customerID
something like the below
SELECT customer_id
INTO #thisMonth
FROM customer
WHERE month_column > DATEADD(month, 0, GETDATE())
SELECT customer_id
INTO #prevMonth
FROM customer
WHERE month_column > DATEADD(month, -1, GETDATE())
SELECT COUNT(customer_id)
FROM #thisMonth tm
INNERJOIN #prevMonth pm ON tm.customer_id = pm.customerID
from the table given below find the count of active sellers for each day in June 2017. A seller is considered active when he has listed at least one item in last 30 days from the transaction date.
sample table:
Well, one method is to generate the dates and use a lateral join to calculate the number of sellers:
with dates as (
select cast('2017-06-01' as date) as dte
union all
select dateadd(day, 1, dte)
from dates
where dte < '2017-06-30'
)
select d.dte, t.num_sellers
from dates d outer apply
(select count(distinct t.seller_id) as num_sellers
from t
where t.transaction_date > dateadd(day, -30, d.dte) and
t.transaction_date <= d.dte
) t
order by d.dte;
I'm using SQL Server. I've a following table Orders:
Orders (Id, ItemId, CustomerId, Quantity, OrderDateTime)
I want to count the number of orders each month. I've written 2 of the following query.
Query #1:
SELECT
MONTH(OrderDateTime) AS MonthCol,
YEAR(OrderDateTime) AS YearCol,
COUNT(id) AS OrderCount
FROM
Orders
WHERE
OrderDateTime >= '2000' AND OrderDateTime <= '2018'
GROUP BY
YEAR(OrderDateTime), MONTH(OrderDateTime)
ORDER BY
YearCol, MonthCol
Query #2:
SELECT
DATEPART(mm, OrderDateTime) AS Month,
COUNT(*) AS OrderCount
FROM
Orders
WHERE
OrderDateTime >= '2000' AND OrderDateTime <= '2018'
GROUP BY
DATEPART(mm, OrderDateTime)
Issue with both queries is that I'm not getting the columns with 0 orders. How will I get it?
SQL will not give you data about months and year which do not exist as rows. To get 0 order rows you'd need to right join the results with a calendar table containing all needed months and years or you can also use a tally table.
Select T.MonthCol, T.YearCol,OrderCount= COALESCE(OrderCount,0)
from
(
SELECT MONTH(OrderDateTime) AS MonthCol, YEAR(OrderDateTime) AS YearCol, count(id) AS OrderCount
FROM Orders
WHERE OrderDateTime >= '2000' AND OrderDateTime <= '2018'
GROUP BY YEAR(OrderDateTime), MONTH(OrderDateTime)
ORDER BY YearCol, MonthCol)
P
RIGHT JOIN
(
select * from
( values (2000),(2001),(2002),(2003),(2004),(2005),(2006),(2007),(2008))v(YearCol)
cross join
( values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12))u(MonthCol)
)T
on P.MonthCol=T.MonthCol
and P.YearCol=T.YearCol
I would be inclined to use a recursive CTE for this -- this gives pretty easy flexibility on the range you want:
with dates as (
select cast('2000-01-01' as date) dte
union all
select dateadd(month, 1, dte)
from dates
where dte < '2018-12-01'
)
select year(OrderDateTime) AS year,
month(OrderDateTime) AS month,
count(o.id) as OrderCount
from dates left join
orders o
on d.OrderDateTime >= dates.dte and
d.OrderDateTime < dateadd(month, 1, dates.dte)
group by year(OrderDateTime), month(OrderDateTime)
order by year(OrderDateTime), month(OrderDateTime)
option (maxrecursion 0);
Notes:
This uses the JOIN to do the filtering. This makes it safer to change the range that you are looking for.
I find the year() and month() functions to be more convenient datepart().
When using date parts, spell them out. Why waste brain power trying to remember if mm really means months or minutes?
I added an order by. Presumably you want the results in chronological order.
My table creates a new record with timestamp daily when an integration is successful. I am trying to create a query that would check (preferably automated) the number of days in a month vs number of records in the table within a time frame.
For example, January has 31 days, so i would like to know how many days in january my process was not successful. If the number of records is less than 31, than i know the job failed 31 - x times.
I tried the following but was not getting very far:
SELECT COUNT (DISTINCT CompleteDate)
FROM table
WHERE CompleteDate BETWEEN '01/01/2015' AND '01/31/2015'
Every 7 days the system executes the job twice, so i get two records on the same day, but i am trying to determine the number of days that nothing happened (failures), so i assume some truncation of the date field is needed?!
One way to do this is to use a calendar/date table as the main source of dates in the range and left join with that and count the number of null values.
In absence of a proper date table you can generate a range of dates using a number sequence like the one found in the master..spt_values table:
select count(*) failed
from (
select dateadd(day, number, '2015-01-01') date
from master..spt_values where type='P' and number < 365
) a
left join your_table b on a.date = b.CompleteDate
where b.CompleteDate is null
and a.date BETWEEN '01/01/2015' AND '01/31/2015'
Sample SQL Fiddle (with count grouped by month)
Assuming you have an Integers table*. This query will pull all dates where no record is found in the target table:
declare #StartDate datetime = '01/01/2013',
#EndDate datetime = '12/31/2013'
;with d as (
select *, date = dateadd(d, i - 1 , #StartDate)
from dbo.Integers
where i <= datediff(d, #StartDate, #EndDate) + 1
)
select d.date
from d
where not exists (
select 1 from <target> t
where DATEADD(dd, DATEDIFF(dd, 0, t.<timestamp>), 0) = DATEADD(dd, DATEDIFF(dd, 0, d.date), 0)
)
Between is not safe here
SELECT 31 - count(distinct(convert(date, CompleteDate)))
FROM table
WHERE CompleteDate >= '01/01/2015' AND CompleteDate < '02/01/2015'
You can use the following query:
SELECT DATEDIFF(day, t.d, dateadd(month, 1, t.d)) - COUNT(DISTINCT CompleteDate)
FROM mytable
CROSS APPLY (SELECT CAST(YEAR(CompleteDate) AS VARCHAR(4)) +
RIGHT('0' + CAST(MONTH(CompleteDate) AS VARCHAR(2)), 2) +
'01') t(d)
GROUP BY t.d
SQL Fiddle Demo
Explanation:
The value CROSS APPLY-ied, i.e. t.d, is the ANSI string of the first day of the month of CompleteDate, e.g. '20150101' for 12/01/2015, or 18/01/2015.
DATEDIFF uses the above mentioned value, i.e. t.d, in order to calculate the number of days of the month that CompleteDate belongs to.
GROUP BY essentially groups by (Year, Month), hence COUNT(DISTINCT CompleteDate) returns the number of distinct records per month.
The values returned by the query are the differences of [2] - 1, i.e. the number of failures per month, for each (Year, Month) of your initial data.
If you want to query a specific Year, Month then just simply add a WHERE clause to the above:
WHERE YEAR(CompleteDate) = 2015 AND MONTH(CompleteDate) = 1
I have tried but i am not able to figure this out. I have a table transactions (transaction_ID, transaction_Person_ID, Transaction_Date etc).
What i want is to return all the transaction_person_ID's that have more than 3 transactions per week for the last year. That means i have to check for 1-1-10 to 7-1-10 to see if someone had more than 3 transactions for that 7 day period, then for 2-1-10 to 8-1-10 then 3-1-10 to 9-1-10 etc etc.
I now i need to use a recursive select but i what i have writen does not produce the correct time frame.
What i have written so far is this
WITH Dates AS (
SELECT
[Date] = CONVERT(DATETIME,'01/01/2010')
UNION ALL SELECT
[Date] = DATEADD(DAY, 1, [Date])
FROM
Dates
WHERE
Date < '12/31/2010'
)
SELECT transaction_person_Id FROM transactions
JOIN DATES
ON transactions.transaction_date = dates.date
where transactions.Transaction_Date between dateadd(DAYOFYEAR,-7,dates.date) and dates.date
group by transaction_person_Id
having count(transaction_person_ID) >= 4
OPTION (MAXRECURSION 2000)
Thanks a lot
PS:
in simple words what i need to do is this
select transaction_person_ID from transactions
where Transaction_Date between '2010-01-01' and '2010-01-07'
group by transaction_person_Id
having count(transaction_person_ID) >= 4
then
select transaction_person_ID from transactions
where Transaction_Date between '2010-01-02' and '2010-01-08'
group by transaction_person_Id
having count(transaction_person_ID) >= 4
.
.
.
.
.
until it goes
select transaction_person_ID from transactions
where Transaction_Date between '2010-12-25' and '2010-12-31'
group by transaction_person_Id
having count(transaction_person_ID) >= 4
i need to have the results of these 365 queries
This will give one result set with person and weeks, rather then 360 results sets
WITH Weeks
AS (
SELECT
CONVERT(DATETIME,'01 Jan 2010') AS WeekStartMidnight,
CONVERT(DATETIME,'08 Jan 2010') AS WeekEndMidnight
UNION ALL
SELECT
DATEADD(day, 1, WeekStartMidnight),
DATEADD(day, 1, WeekEndMidnight)
FROM
Weeks
WHERE
WeekEndMidnight < '31 Dec 2010'
)
SELECT
t.transaction_person_Id,
w.WeekStartMidnight, w.WeekEndMidnight
FROM
weeks w
JOIN
transactions t ON t.Transaction_Date >= w.WeekStartMidnight AND t.Transaction_Date < w.WeekEndMidnight
GROUP BY
t.transaction_person_Id
HAVING
count(*) >= 4 --COUNT(t.transaction_person_Id) = same
OPTION
(MAXRECURSION 365)
If you want 360 results sets, it's a loop using WHILE or a CURSOR per row in the "weeks" derived table