Customized week number with date - sql

How can I make the start of the week 1 from 5/1/2016 and the end of the week 52 at 4/30/2017. For example: 5/1/2016 - 5/7/2016 should be week 1. SQL Server has the week counting with respect to the fiscal year. Is this possible? I am using SQL Server 2016.
select order_date,
datepart(week from order_date)weekorder, product_code
from my_table
where order_date > '4/30/2016'
and order_date < '5/1/2017'
order_date weekorder product_code
2017-03-01 9 16PSS
2016-11-26 48 16PZS
2016-11-18 47 16PSST
2016-05-31 23 16PRS
Requested:
order_date weekorder product_code
2017-03-01 47 16PSS
2016-11-26 22 16PZS
2016-11-18 21 16PSST
2016-05-31 5 16PRS

Well, you can use date arithmetic:
select order_date,
datediff(day, '2016-04-30', order_date) / 7 as weekorder,
product_code
from my_table
where order_date > '2016-04-30' and
order_date < '2017-05-01';

Related

Using Bigquery , how to use conditional statement involving dates

I require a column which counts the number days i.e(Order Date - 01Jan2020).
Condition is -> if Order Date lies between 01Jan2020 and 31Mar2020
then (DATE_DIFF('2020-01-31' ,Order Date, DAY))
else 0
Question -> how to use this condition statement in BigQuery ?
Table -
Customer ID | Order Date
298 | 2020-02-28
78 | 2020-04-02
31 | 2021-01-09
345 | 2021-09-09
74 | 2020-01-20
I tried -
if((Order Date <'2020-01-01') and (Order Date >'2020-03-31'),(DATE_DIFF('2020-01-31' ,Order Date, DAY)
,0))
Try SELECT statement with WHERE clause:
SELECT id, orderdate, DATE_DIFF('2020-01-31', orderdate, DAY) as datediff FROM `yourdataset.ordertable`
WHERE orderdate BETWEEN '2020-01-01' AND '2020-03-31';
Output:
id orderdate datediff
298 2020-02-28 -28
74 2020-01-20 11
CASE statement:
SELECT
id,
orderdate,
CASE
WHEN (orderdate BETWEEN '2020-01-01' AND '2020-03-31') THEN DATE_DIFF('2020-01-31', orderdate, DAY)
ELSE 0
END AS `datediff`
FROM `yourdataset.ordertable`
Output:
id orderdate datediff
78 02/04/20 0
298 28/02/20 -28
345 09/09/21 0
31 09/01/21 0
74 20/01/20 11
Try below syntax: Once able to run it. Replace current_date with Order_Date. Hope this will work.
select
if(current_date <'2020-01-01' and current_date >'2020-03-31' ,DATE_DIFF('2020-01-31' ,current_date, DAY),0);

check whether values lies between or not in SQL

These are my 2 tables
table 2:
date_val
yr_num
yr_wk_num
day_wk_num
yr_wk_nm
day
mo_num
20200808
2020
32
6
202032
Saturday
08
20200809
2020
32
7
202032
Sunday
08
20200810
2020
33
1
202033
Monday
08
20200811
2020
33
2
202033
Tuesday
08
20200812
2020
33
3
202033
Wednesday
08
table1:
sku_id
dateval
sales
ab124
20210603
10
ab124
20210502
20
ab123
20210606
30
Need to check sales is with in + or - 30% of 2 month avg sales
with CTE
as
(
select * from table1 where dateval >= dateadd(mm, -2, dateval)
)
select dateval, sum(sales) as [Total Sales], avg(sales) as [Average Sales] from CTE group by dateval order by 1
I tried below also...
with CTE
as
(
select * from table1 t1 left join table2 t2 on t1.dateval = t2.date_val where t2.date_val >= dateadd(mm, -2, t1.dateval)
)
select dateval,sum(sales) as [Total Sales], avg(sales) as [Average Sales] from CTE group by dateval order by 1
here am doing filtering within table1 but i need to use table 2 to get filtered for past two months and get avg sales.
Next, i need to do +30% to that result avg and -30% result avg and check whether my sales is withn avg sales( avg30% above or below) or not if yes '1' if not '0'
For Ex:
Historic 2 month avg sales 100.
(+30% of avg sales is 130)
(-30% of avg sales is 70)
if sales is 120. i need to check 120 lies between 70 to 130.
please suggest me how to achieve

How can I selectively NULL out values from one column but not another?

If I select all from my dbo.targetsvssales table I get the following result:
Date | Sales | Targets
_____________________________
2017-01-01 10 10
2017-02-01 19 20
2017-03-01 31 30
2017-04-01 38 40
2017-05-01 49 50
2017-06-01 62 60
2017-07-01 70 70
2017-08-01 75 80
2017-09-01 88 90
2017-10-01 101 100
2017-11-01 105 110
2017-12-01 105 120
I would like to only select the sales data that is from a date less than the current date, leaving the result of future dates as null, but keep the target values as they are. So the desired result from the select statement would be:
Date | Sales | Targets
_____________________________
2017-01-01 10 10
2017-02-01 19 20
2017-03-01 31 30
2017-04-01 38 40
2017-05-01 49 50
2017-06-01 62 60
2017-07-01 70 70
2017-08-01 75 80
2017-09-01 88 90
2017-10-01 101 100
2017-11-01 105 110
2017-12-01 NULL 120
This needs to be able to work year round, as well as on tables with weekly and daily precision as the Date column, so something that uses
WHERE DATE > GETDATE()
or something similar would be ideal. Any help or advice would be greatly appreciated.
Use case to define the result for this column:
CASE WHEN DATE <= GETDATE()
THEN Sales
END AS Sales
Note I've reversed your logic and skipped the else null because this is anyway default if omitted.
More about case: http://modern-sql.com/feature/case
Case will work for this problem.
CASE WHEN DATE<=GETDATE() THEN Sales ELSE NULL END
You can use Cas When statement
select date,
CASE
WHEN Date <= GETDATE()
THEN Sales
else NULL
End as Sales,
targets
from dbo.targetsvssales
DECLARE #targetsvssales AS TABLE ([Date] DATE, Sales MONEY, Targets MONEY)
INSERT INTO #targetsvssales VALUES
('2017-01-01',10,10),
('2017-02-01',19,20),
('2017-03-01',31,30),
('2017-04-01',38,40),
('2017-05-01',49,50),
('2017-06-01',62,60),
('2017-07-01',70,70),
('2017-08-01',75,80),
('2017-09-01',88,90),
('2017-10-01',101,100),
('2017-11-01',105,110),
('2017-12-01',105,120)
SELECT
[Date]
,CASE WHEN [DATE] > GETDATE() THEN NULL ELSE Sales END AS Sales
,Targets
FROM #targetsvssales
Use this :
select Date, case when Date > getdate() then NULL else Sales end as Sales, Targets
from dbo.targetsvssales
SQL HERE
Use ROW_NUMBER and CASE:
CREATE TABLE T (
MDate DATE,
Sales INT,
Targetes INT
);
INSERT INTO T VALUES
('2017-01-01', 10 , 10),
('2017-02-01', 19 , 20),
('2017-03-01', 31 , 30),
('2017-04-01', 38 , 40),
('2017-05-01', 49 , 50),
('2017-06-01', 62 , 60),
('2017-07-01', 70 , 70),
('2017-08-01', 75 , 80),
('2017-09-01', 88 , 90),
('2017-10-01', 101, 100),
('2017-11-01', 105, 110),
('2017-12-01', 105, 120);
WITH CTE AS (
SELECT *, ROW_NUMBER () OVER (PARTITION BY Sales ORDER BY MDate) RN
FROM T
)
SELECT MDate, CASE WHEN RN = 1 THEN Sales ELSE NULL END AS Sales, Targetes
FROM CTE;
If you really want to compare with GETDATE(), then I'll suggest using IIF or CASE as:
SELECT MDate, IIF(IIF(MDate <= GetDate(), Sales, NULL) AS Sales, Targetes
FROM T;
Demo

SQL Server : number of orders per date with day column

I have a query that pulls number of orders per date.
SELECT
name, CONVERT(VARCHAR(10), order_date, 120) AS order_date,
COUNT(1) AS orders
FROM
orders AS od
WHERE
id = 73
GROUP BY
CONVERT(VARCHAR(10), order_date, 120), name
ORDER BY
order_date, name
Below are the results I get when I run the query:
name order_date orders
--------------------------
20pmam 2016-07-27 39
20pmam 2016-07-28 30
20pmam 2016-07-29 32
20pmam 2016-07-31 468
20pmam 2016-08-02 75
20pmam 2016-07-05 30
I need my results to be like this, with a new column day
name order_date orders day
-------------------------------
20pmam 2016-07-27 39 1
20pmam 2016-07-28 30 2 // days between 2016-07-27 to 2016-07-28
20pmam 2016-07-29 32 3 // days between 2016-07-27 to 2016-07-29
20pmam 2016-07-31 468 5 // days between 2016-07-27 to 2016-07-31
20pmam 2016-08-02 75 7 // days between 2016-07-27 to 2016-08-02
20pmam 2016-08-05 30 10 // days between 2016-07-27 to 2016-08-05
The first/minimum order_date should be taken as day 1 ( in the above results 2016-07-27 is day 1) and should calculate others based on the first/minimum order_date.
Is this easily possible?
I don't have any idea how to get the desired result. I would appreciate any suggestions.
You can do this cross apply to get the minimum date before each order_date and use it in datediff.
SELECT name,CONVERT(VARCHAR(10), order_date, 120) AS order_date, Count(1) [orders],
1+coalesce(datediff(day,t.min_date,od.order_date),0) as [Day]
FROM orders AS od
cross apply (select min(od1.order_date) as min_date
from orders od1
where od.id=od1.id and od.name=od1.name and od1.order_date<od.order_date) t
WHERE id = 73
GROUP BY CONVERT(VARCHAR(10), order_date, 120),name,datediff(day,t.min_date,od.order_date)
ORDER BY order_date,name
Try something like:
SELECT name,
CONVERT(VARCHAR(10), order_date, 120) AS order_date,
Count(1) AS orders,
DATEDIFF(DAY, first_order_date, order_date) + 1
FROM orders AS od
JOIN (SELECT min(order_date) AS first_order_date
FROM orders) as fod ON 1 = 1
WHERE id = 73
GROUP BY CONVERT(VARCHAR(10), order_date, 120),
name,
DATEDIFF(DAY, first_order_date, order_date) + 1
ORDER BY order_date,
name
Hope this will solve your problem

Aggregate multiple columns based on specific date range with in a month

I need to aggregate Amounts to be displayed by date range per month. To illustrate please take a look at the following table:
Invoice_Payment
Customer_id Invoice_no Invoice_date Amount
---------------------------------------------------
10 10023 2016-07-08 60
10 10018 2016-08-04 90
11 10016 2016-07-01 110
11 10021 2016-07-05 120
12 10028 2016-07-11 10
12 10038 2016-07-31 5
As you'll notice, I want to group them based on Customer_id and display the dates from start to end. Furthermore, this has to be done for each month only.
Following query I have tried so far:
select Customer_id, (mindate + ' to ' + maxdate) Date_Range, Amount
from (
select Customer_id, sum(Amount) Amount, min(Invoice_date) mindate, max(Invoice_date) maxdate
from Invoice_Payment
group by Customer_id
) I ;
From above query I'm getting Output like:
Customer_id Date_Range Amount
10 2016-07-08 to 2016-08-04 150
11 2016-07-01 to 2016-07-05 230
12 2016-07-11 to 2016-07-31 15
Please check this.. SQL Fiddle Working Demo
Let's say Customer_id = 10 who has Invoice_date in July,2016 and August,2016. I need to sum up all payments of that particular Customer for the month of July and August separately within specific date range. But I am getting sum of Amount of all Invoice_date from above endeavor.
Desired output :
Customer_id Date_Range Amount
10 2016-07-08 to 2016-07-08 60
10 2016-08-04 to 2016-08-04 90
11 2016-07-01 to 2016-07-05 230
12 2016-07-11 to 2016-07-31 15
How could I get over this ? Any help would be greatly appreciated.
You are almost done. Just add YEAR and MONTH to GROUP BY.
select Customer_id, (mindate + ' to ' + maxdate) Date_Range, Amount
from (
select Customer_id,
sum(Amount) Amount, min(Invoice_date) mindate, max(Invoice_date) maxdate
from #Invoice_Payment
group by
Customer_id,
YEAR(Invoice_date),
MONTH(Invoice_date)
) I ;
How about grouping by customer_id, month and year
select Customer_id, (mindate + ' to ' + maxdate) Date_Range, Amount
from (
select Customer_id,
sum(Amount) Amount, min(Invoice_date) mindate, max(Invoice_date) maxdate
from #Invoice_Payment
group by Customer_id,month(Invoice_date), year(Invoice_date)
) I
order by customer_id;