How to update column with average weekly value for each day in sql - sql

I have the following table. I insert a column named WeekValue, I want to fill the weekvalue column with the weekly average value of impressionCnt of the same category for each row.
Like:
+-------------------------+----------+---------------+--------------+
| Date | category | impressioncnt | weekAverage |
+-------------------------+----------+---------------+--------------+
| 2014-02-06 00:00:00.000 | a | 123 | 100 |
| 2014-02-06 00:00:00.000 | b | 121 | 200 |
| 2014-02-06 00:00:00.000 | c | 99 | 300 |
| 2014-02-07 00:00:00.000 | a | 33 | 100 |
| 2014-02-07 00:00:00.000 | b | 456 | 200 |
| 2014-02-07 00:00:00.000 | c | 54 | 300 |
| 2014-02-08 00:00:00.000 | a | 765 | 100 |
| 2014-02-08 00:00:00.000 | b | 78 | 200 |
| 2014-02-08 00:00:00.000 | c | 12 | 300 |
| ..... | | | |
| 2014-03-01 00:00:00.000 | a | 123 | 111 |
| 2014-03-01 00:00:00.000 | b | 121 | 222 |
| 2014-03-01 00:00:00.000 | c | 99 | 333 |
| 2014-03-02 00:00:00.000 | a | 33 | 111 |
| 2014-03-02 00:00:00.000 | b | 456 | 222 |
| 2014-03-02 00:00:00.000 | c | 54 | 333 |
| 2014-03-03 00:00:00.000 | a | 765 | 111 |
| 2014-03-03 00:00:00.000 | b | 78 | 222 |
| 2014-03-03 00:00:00.000 | c | 12 | 333 |
+-------------------------+----------+---------------+--------------+
I tried
update [dbo].[RetailTS]
set Week = datepart(day, dateDiff(day, 0, [Date])/7 *7)/7 +1
To get the week numbers then try to group by the week week number and date and category, but this seems isn't correct. How do I write the SQL query? Thanks!

Given that you may be adding more data in the future, thus requiring another update, you might want to just select out the weekly averages:
SELECT
Date,
category,
impressioncnt,
AVG(impressioncnt) OVER
(PARTITION BY category, DATEDIFF(d, 0, Date) / 7) AS weekAverage
FROM RetailTS
ORDER BY
Date, category;

Related

Query last unt price before with detail record

sample
+---------+------------+----------+------------+
| prdt_no | order_date | quantity | unit_price |
+---------+------------+----------+------------+
| A001 | 2020-01-01 | 100 | 10 |
| A001 | 2020-01-10 | 200 | 10 |
| A001 | 2020-02-01 | 100 | 20 |
| A001 | 2020-02-05 | 100 | 20 |
| A001 | 2020-02-07 | 100 | 20 |
| A001 | 2020-02-10 | 100 | 15 |
| A002 | 2020-01-01 | 100 | 10 |
| A002 | 2020-01-10 | 200 | 10 |
| A002 | 2020-02-01 | 100 | 20 |
| A002 | 2020-02-05 | 100 | 20 |
| A002 | 2020-02-07 | 100 | 20 |
| A002 | 2020-02-10 | 100 | 15 |
+---------+------------+----------+------------+
expected
if query condition is order_date between 2020-02-02 and 2020-02-10 then the data will be expected to get below result
+---------+------------+----------+------------+------------------------+-----------------+-------------+-----------------------------+
| prdt_no | order_date | quantity | unit_price | last_unit_price_before | unit_price_diff | cost_reduce | last_unit_price_change_date |
+---------+------------+----------+------------+------------------------+-----------------+-------------+-----------------------------+
| A001 | 2020-02-05 | 100 | 20 | 10 | 10 | 1000 | 2020-02-01 |
| A001 | 2020-02-07 | 100 | 20 | 10 | 10 | 1000 | 2020-02-01 |
| A001 | 2020-02-10 | 100 | 15 | 20 | -5 | -500 | 2020-02-10 |
| A002 | 2020-02-05 | 100 | 20 | 10 | 10 | 1000 | 2020-02-01 |
| A002 | 2020-02-07 | 100 | 20 | 10 | 10 | 1000 | 2020-02-01 |
| A002 | 2020-02-10 | 100 | 15 | 20 | -5 | -500 | 2020-02-10 |
+---------+------------+----------+------------+------------------------+-----------------+-------------+-----------------------------+
logic
I hope to get same product last unit price before then use it to calculate the price difference
the data record count actually over 200K
like photo
test demo link
SQL Server 2012 | db<>fiddle
you can use OUTER APPLY() to get the last low with price difference
SELECT *,
unit_price_diff = T.[unit_price] - L.[last_unit_price_before]
FROM T
OUTER APPLY
(
SELECT TOP 1
last_unit_price_before = x.[unit_price],
last_unit_price_change_date = x.[order_date]
FROM T x
WHERE x.[prdt_no] = T.[prdt_no]
AND x.[order_date] < T.[order_date]
AND x.[unit_price] <> T.[unit_price]
ORDER BY x.[order_date] DESC
) L
WHERE T.[order_date] >= '2020-02-01'
AND T.[order_date] <= '2020-02-10'
db<>fiddle

SQL multiple sum by PARTITION

I have the following postgreSql table stock, there the structure is following
| column | pk |
+--------+-----+
| date | yes |
| id | yes |
| type | yes |
| qty | |
| fee | |
table looks like this
| date | id | type | qty | fee |
+------------+-----+------+------+------+
| 2015-01-01 | 001 | CB04 | 500 | 2 |
| 2015-01-01 | 002 | CB04 | 1500 | 3 |
| 2015-01-01 | 003 | CB04 | 500 | 1 |
| 2015-01-01 | 004 | CB04 | 100 | 5 |
| 2015-01-01 | 001 | CB02 | 800 | 6 |
| 2015-01-02 | 002 | CB03 | 3100 | 1 |
| | | | | |
I want to create a view or query, so that the result looks like this.
| date | type | t_qty | total_weighted_fee |
+------------+------+-------+--------------------+
| 2015-01-01 | CB04 | 2600 | 2.5 |
| 2015-01-01 | CB03 | 3100 | 1 |
| | | | |
what I did is this
http://sqlfiddle.com/#!17/39fb8a/18
But this is not the output what I want.
The Sub Query table looks like this:
% of total Qty = qty / t_qty
weighted fee = fee * % of total Qty
| date | id | type | qty | fee | t_qty | % of total Qty | weighted fee |
+------------+-----+------+------+-----+-------+----------------+--------------+
| 2015-01-01 | 001 | CB04 | 500 | 2 | 2600 | 0.19 | 0.38 |
| 2015-01-01 | 002 | CB04 | 1500 | 3 | 2600 | 0.58 | 1.73 |
| 2015-01-01 | 003 | CB04 | 500 | 1 | 2600 | 0.19 | 0.192 |
| 2015-01-01 | 004 | CB04 | 100 | 5 | 2600 | 0.04 | 0.192 |
| 2015-01-01 | 002 | CB03 | 3100 | 1 | 3100 | 1 | 1 |
| | | | | | | | |
You can use aggregation . . . I don't think you are far off:
select date, type, sum(qty),
sum(fee * qty * 1.0) / nullif(sum(qty), 0)
from t
group by date, type;

update a value column of a row based in another value of row

I have a historical table with data as bellow :
In my case the product id (110,111,112) had changed the price that way i have the same product with the value of the product_updateDate also sometimes i can have the same duplicate data with no information changed
+------+------------+--------------+---------------+-----------------------------+-------------------------+-------------------------+----------------+
| id | product_id | product_name | product_Price | product_addDate | product_UpdateDate | Insertdate_DB | Updatedate_DB |
+------+------------+--------------+---------------+-----------------------------+-------------------------+-------------------------+----------------+
| 1 | 110 | DELL | 1000 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 2 | 111 | HP | 900 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 3 | 112 | Mac | 1300 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 4 | 113 | Lenovo | 950 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 5 | 110 | DELL | 900 | 2017-03-04 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-07 10:00:00.000 | NULL |
| 6 | 111 | HP | 800 | 2017-03-04 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-07 10:00:00.000 | NULL |
| 7 | 112 | Mac | 120 | 2017-03-04 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-07 10:00:00.000 | NULL |
+------+------------+--------------+---------------+-----------------------------+-------------------------+-------------------------+----------------+
What i want is doing an Update Query to get the result as bellow:
+----+------------+--------------+---------------+-------------------------+-------------------------+-------------------------+---------------+
| id | product_id | product_name | product_Price | product_addDate | product_UpdateDate | Insertdate_DB | Updatedate_DB |
+----+------------+--------------+---------------+-------------------------+-------------------------+-------------------------+---------------+
| 1 | 110 | DELL | 1000 | 2017-03-01 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-06 10:00:00.000 | GETDATE() |
| 2 | 111 | HP | 900 | 2017-03-01 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-06 10:00:00.000 | GETDATE() |
| 3 | 112 | Mac | 1300 | 2017-03-01 08:00:00.000 | 2017-03-04 08:00:00.000 | 2017-03-06 10:00:00.000 | GETDATE() |
| 4 | 113 | Lenovo | 950 | 2017-03-01 08:00:00.000 | NULL | 2017-03-06 10:00:00.000 | NULL |
| 5 | 110 | DELL | 900 | 2017-03-04 08:00:00.000 | NULL | 2017-03-07 10:00:00.000 | NULL |
| 6 | 111 | HP | 800 | 2017-03-04 08:00:00.000 | NULL | 2017-03-07 10:00:00.000 | NULL |
| 7 | 112 | Mac | 120 | 2017-03-04 08:00:00.000 | NULL | 2017-03-07 10:00:00.000 | NULL |
+----+------------+--------------+---------------+-------------------------+-------------------------+-------------------------+---------------+
The query as bellow can update the product_UpdateDate
update tablename
set product_UpdateDate = case when tablename.product_UpdateDate is null
then t.product_UpdateDate
else null end
from tablename
join tablename t
on tablename.product_id = t.product_id
and t.ID <> tablename.id `
But also i want to change the Updatedate_DB with the GETDATE() value when i try to do update this column all rows have the value GETDATE() but i want change only the rows that the value have change
Thanks for help
I think row_number() might be a simpler method. The logic is hard to follow, but the following should result in the data in your question:
with toupdate as (
select t.*,
row_number() over (partition by product_id order by id) as seqnum,
count(*) over (partition by product_id) as cnt
from t
)
update toupdate
set product_UpdateDate = (case when seqnum = 1 then product_addDate end),
Updatedate_DB = (case when seqnum = 1 then getdate() end)
where cnt > 1;

Will Inner join allow duplicates?

if join two tables using inner join method will it return duplicate values ?
Yes, if there are duplicate values.
If you have CUSTOMERS table:
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
| 7 | Muffy | 24 | Indore | 10000.00 |
+----+----------+-----+-----------+----------+
and ORDERS table as follows:
+-----+---------------------+-------------+--------+
| OID | DATE | CUSTOMER_ID | AMOUNT |
+-----+---------------------+-------------+--------+
| 102 | 2009-10-08 00:00:00 | 3 | 3000 |
| 100 | 2009-10-08 00:00:00 | 3 | 1500 |
| 101 | 2009-11-20 00:00:00 | 2 | 1560 |
| 103 | 2008-05-20 00:00:00 | 4 | 2060 |
+-----+---------------------+-------------+--------+
Then inner join will give result:
SELECT ID, NAME, AMOUNT, DATE
FROM CUSTOMERS
INNER JOIN ORDERS
ON CUSTOMERS.ID = ORDERS.CUSTOMER_ID;
This would produce the following result:
+----+----------+--------+---------------------+
| ID | NAME | AMOUNT | DATE |
+----+----------+--------+---------------------+
| 3 | kaushik | 3000 | 2009-10-08 00:00:00 |
| 3 | kaushik | 1500 | 2009-10-08 00:00:00 |
| 2 | Khilan | 1560 | 2009-11-20 00:00:00 |
| 4 | Chaitali | 2060 | 2008-05-20 00:00:00 |
+----+----------+--------+---------------------+
Here is an example with duplicate rows in both tables.
select * from customers;
id | name | age | address
----+-------------+-----+-----------
1 | Ramesh | 32 | Ahmedabad
2 | Khilan | 25 | Delhi
3 | kaushik | 23 | Kota <-- id 3 "kaushik"
3 | kaushik_two | 23 | Ahmedabad <-- appears twice
4 | Chaitali | 25 | Mumbai
5 | Hardik | 27 | Bhopal
6 | Komal | 22 | MP
7 | Muffy | 24 | Indore
(8 rows)
select * from orders;
oid | date | customer_id | amount
-----+---------------------+-------------+--------
102 | 2009-10-08 00:00:00 | 3 | 3000 <-- reference to customer 3
100 | 2009-10-08 00:00:00 | 3 | 1500 <-- also appears twice
101 | 2009-11-20 00:00:00 | 2 | 1560
103 | 2008-05-20 00:00:00 | 4 | 2060
104 | 2022-01-01 00:00:00 | 100 | 3900
(5 rows)
Inner Join
Produces duplicated rows for "kaushik" and "kaushik_two".
select id, name, amount, date
from customers
inner join orders on customers.id = orders.customer_id;
id | name | amount | date
----+-------------+--------+---------------------
2 | Khilan | 1560 | 2009-11-20 00:00:00
3 | kaushik | 1500 | 2009-10-08 00:00:00 <-- first pair
3 | kaushik | 3000 | 2009-10-08 00:00:00
3 | kaushik_two | 1500 | 2009-10-08 00:00:00 <-- second pair
3 | kaushik_two | 3000 | 2009-10-08 00:00:00
4 | Chaitali | 2060 | 2008-05-20 00:00:00
(6 rows)

Count rows each month of a year - SQL Server

I have a table "Product" as :
| ProductId | ProductCatId | Price | Date | Deadline |
--------------------------------------------------------------------
| 1 | 1 | 10.00 | 2016-01-01 | 2016-01-27 |
| 2 | 2 | 10.00 | 2016-02-01 | 2016-02-27 |
| 3 | 3 | 10.00 | 2016-03-01 | 2016-03-27 |
| 4 | 1 | 10.00 | 2016-04-01 | 2016-04-27 |
| 5 | 3 | 10.00 | 2016-05-01 | 2016-05-27 |
| 6 | 3 | 10.00 | 2016-06-01 | 2016-06-27 |
| 7 | 1 | 20.00 | 2016-01-01 | 2016-01-27 |
| 8 | 2 | 30.00 | 2016-02-01 | 2016-02-27 |
| 9 | 1 | 40.00 | 2016-03-01 | 2016-03-27 |
| 10 | 4 | 15.00 | 2016-04-01 | 2016-04-27 |
| 11 | 1 | 25.00 | 2016-05-01 | 2016-05-27 |
| 12 | 5 | 55.00 | 2016-06-01 | 2016-06-27 |
| 13 | 5 | 55.00 | 2016-06-01 | 2016-01-27 |
| 14 | 5 | 55.00 | 2016-06-01 | 2016-02-27 |
| 15 | 5 | 55.00 | 2016-06-01 | 2016-03-27 |
I want to create SP count rows of Product each month with condition Year = CurrentYear , like :
| Month| SumProducts | SumExpiredProducts |
-------------------------------------------
| 1 | 3 | 3 |
| 2 | 3 | 3 |
| 3 | 3 | 3 |
| 4 | 2 | 2 |
| 5 | 2 | 2 |
| 6 | 2 | 2 |
What should i do ?
You can use a query like the following:
SELECT MONTH([Date]),
COUNT(*) AS SumProducts ,
COUNT(CASE WHEN [Date] > Deadline THEN 1 END) AS SumExpiredProducts
FROM mytable
WHERE YEAR([Date]) = YEAR(GETDATE())
GROUP BY MONTH([Date])