I have a table ORDERS with a column named cache_total_price, spent by each client.
+----+-----------+------------+-----------+------------------+
| id | client_id | date | reference | cache_total_price|
+----+-----------+------------+-----------+------------------+
| 1 | 20 | 2019-01-01 | 004214 | 0 |
| 2 | 3 | 2019-01-03 | 007120 | 0 |
| 3 | 11 | 2019-01-04 | 002957 | 0 |
| 4 | 6 | 2019-01-07 | 003425 | 0 |
I have another table ORDERS_REFS where there is the price total spent for each orders id
+-----+-------------+------------+----------+---------------+------------+
| id | order_id | name | quantity | unit_price | total_price|
+-----+-------------+------------+----------+---------------+------------+
| 1 | 1 | Produit 19 | 3 | 49.57 | 148.71 |
| 2 | 1 | Produit 92 | 4 | 81.24 | 324.96 |
| 3 | 1 | Produit 68 | 2 | 17.48 | 34.96 |
| 4 | 2 | Produit 53 | 4 | 83.69 | 334.76 |
| 5 | 2 | Produit 78 | 6 | 5.99 | 35.94 |
I want to had to column cache_total_price the result of my query :
select sum(total_price) from orders_refs group by order_id;
result :
+--------------------+
| sum(total_price) |
+--------------------+
| 508.6299819946289 |
| 370.700008392334 |
| 132.3699951171875 |
| 2090.1800079345703 |
I've tried some queries with Insert into select or update set, but didn't worked :(
If you're wanting to update all the orders at once, in MySQL a subquery like this should do the trick. You could always add a WHERE clause to do one at a time.
UPDATE ORDERS
SET cache_total_price = (
SELECT sum(total_price) from ORDERS_REF where order_id = ORDERS.id
)
update t
set t.cache_total_price=x.sum_total_price
from ORDERS as t
join
(
select order_id,sum(total_price)as sum_total_price
from orders_refs group by order_id
)x on t.id=x.order_id
In SQL Server you can try this one.
I want to calculate the number of people who also had occurrence the previous day on a daily basis, but I'm not sure how to do this?
Sample Table:
| ID | Date |
+----+-----------+
| 1 | 1/10/2020 |
| 1 | 1/11/2020 |
| 2 | 2/20/2020 |
| 3 | 2/20/2020 |
| 3 | 2/21/2020 |
| 4 | 2/23/2020 |
| 4 | 2/24/2020 |
| 5 | 2/22/2020 |
| 5 | 2/23/2020 |
| 5 | 2/24/2020 |
+----+-----------+
Desired Output:
| Date | Count |
+-----------+-------+
| 1/11/2020 | 1 |
| 2/21/2020 | 1 |
| 2/23/2020 | 1 |
| 2/24/2020 | 2 |
+-----------+-------+
Edit: Added desired output. The output count should be unique to the ID, not the number of date occurrences. i.e. an ID 5 can appear on this list 10 times for dates 2/23/2020 and 2/24/2020, but that would count as "1".
Use lag():
select date, count(*)
from (select t.*, lag(date) over (partition by id order by date) as prev_date
from t
) t
where prev_date = dateadd(day, -1, date)
group by date;
I am attempting to find which "replenishment" (a positive transaction quantity) can be matched to a "requirement" (a negative transaction quantity).
The basic logic would be: For a given requirement, find the first available replenishment (whether that replenishment be from existing inventory, or from an upcoming change).
I am working with a table dbo_purchases_new that looks like this:
| Element_ID | Element | Transaction_Date | Transaction_Quantity | Total_Inventory |
|:----------:|:----------:|:----------------:|:--------------------:|:---------------:|
| | STOCK | | 5 | 5 |
| MO302 | Make_Order | 1/3/2019 | 1 | 6 |
| SO105 | Sale | 2/1/2019 | -1 | 5 |
| SO106 | Sale | 2/1/2019 | -1 | 4 |
| MO323 | Make_Order | 2/2/2019 | 1 | 5 |
| SO107 | Sale | 2/4/2019 | -1 | 4 |
| SO191 | Sale | 2/5/2019 | -1 | 3 |
| SO123 | Sale | 2/6/2019 | -1 | 2 |
| SO166 | Sale | 3/1/2019 | -1 | 1 |
| SO819 | Sale | 3/5/2019 | -1 | 0 |
| SO603 | Sale | 3/10/2019 | -4 | -3 |
| MO400 | Make_Order | 3/15/2019 | 1 | -2 |
| MO459 | Make_Order | 3/15/2019 | 1 | -1 |
| MO460 | Make_Order | 3/18/2019 | 1 | 0 |
| MO491 | Make_Order | 3/19/2019 | 1 | 1 |
| MO715 | Make_Order | 4/1/2019 | 3 | 4 |
| SO100 | Sale | 4/2/2019 | -1 | 3 |
| SO322 | Sale | 4/3/2019 | -1 | 2 |
| SO874 | Sale | 4/4/2019 | -1 | 1 |
| SO222 | Sale | 4/5/2019 | -1 | 0 |
| MO999 | Make_Order | 4/5/2019 | 1 | 1 |
| SO999 | Sale | 4/6/2019 | -1 | 0 |
that is being created as a result of this question.
I am now attempting to track which Make_Order will fulfill which Sale by tracking the Transaction_Quantity.
Ideally, the resulting dataset would look like this, where Replenishment and Replenishment_Date are newly added columns:
| Element_ID | Element | Transaction_Date | Transaction_Quantity | Total_Inventory | Replenishment | Replenishment_Date |
|:----------:|:----------:|:----------------:|:--------------------:|:---------------:|:-------------:|:------------------:|
| | STOCK | | 5 | 5 | NULL | NULL |
| MO302 | Make_Order | 1/3/2019 | 1 | 6 | NULL | NULL |
| SO105 | Sale | 2/1/2019 | -1 | 5 | STOCK | NULL |
| SO106 | Sale | 2/1/2019 | -1 | 4 | STOCK | NULL |
| MO323 | Make_Order | 2/2/2019 | 1 | 5 | NULL | NULL |
| SO107 | Sale | 2/4/2019 | -1 | 4 | STOCK | NULL |
| SO191 | Sale | 2/5/2019 | -1 | 3 | STOCK | NULL |
| SO123 | Sale | 2/6/2019 | -1 | 2 | STOCK | NULL |
| SO166 | Sale | 3/1/2019 | -1 | 1 | MO302 | 1/3/2019 |
| SO819 | Sale | 3/5/2019 | -1 | 0 | MO323 | 2/2/2019 |
| SO603 | Sale | 3/10/2019 | -4 | -3 | MO460 | 3/18/2019 |
| MO400 | Make_Order | 3/15/2019 | 1 | -2 | NULL | NULL |
| MO459 | Make_Order | 3/15/2019 | 1 | -1 | NULL | |
| MO460 | Make_Order | 3/18/2019 | 1 | 0 | NULL | NULL |
| MO491 | Make_Order | 3/19/2019 | 1 | 1 | NULL | NULL |
| MO715 | Make_Order | 4/1/2019 | 3 | 4 | NULL | NULL |
| SO100 | Sale | 4/2/2019 | -1 | 3 | MO491 | 3/19/2019 |
| SO322 | Sale | 4/3/2019 | -1 | 2 | MO715 | 4/1/2019 |
| SO874 | Sale | 4/4/2019 | -1 | 1 | MO715 | 4/1/2019 |
| SO222 | Sale | 4/5/2019 | -1 | 0 | MO715 | 4/1/2019 |
| MO999 | Make_Order | 4/5/2019 | 1 | 1 | NULL | NULL |
| SO999 | Sale | 4/6/2019 | -1 | 0 | SO999 | 4/5/2019 |
The ruleset would essentially be:
For a given requirement (a negative transaction quantity of arbitrary value), find which replenishment (a positive transaction quantity of arbitrary value) satisfies it.
Stock is assigned to the first requirements until it runs out. NOTE
-- it could be the case that stock does not exist, so this only applies IF stock does exist
Then, map replenishments to requirements based on the
Transaction_Date in ASC order
I am very confused on how to accomplish this. I imagine some pseudocode would look something like:
for curr in transaction_quantity:
if curr < 0:
if stock.exists() and stock.notempty():
fill in data from that
else:
find next replenishment
fill in data from that
else:
next
Right now, I have this so far, but I know that it will not run. I am very confused on where to go from here. I have tried looking at posts like this, but that did not have an answer. I then tried looking up CURSOR, but that was very confusing to me and I am unsure how I can apply that to this problem.
/****** WiP Script ******/
SELECT
[jerry].[dbo].[purchases_new].*,
CASE WHEN Transaction_Quantity < 0 THEN -- (SELECT Element_ID FROM the_current_row WHERE transaction_quantity > 0)
ELSE NULL AS "Replenishment",
-- (SELECT Transaction_Date FROM [jerry].[dbo].[purchases_new] WHERE Element_ID
-- Not sure how to grab the correct date of the element id from the column before
FROM
[jerry].[dbo].[purchases_new]
Any assistance is appreciated. I have been pulling my hair out on this problem. The comments contain additional information.
NOTE - I have continually tried to update this question as users have requested more information.
Here is one attempt. You will need to modify if with another layer of abstraction for offsets if you need to support transaction increments/decrements > 1. It basically aligns the order of sales with the order of debits and then uses that as join back to the main dataset.
Sql Fiddle
The idea is to put additions and subtractions into two sets, orderd chronologically by set, while also remembering order of each item back into the main list. This way, you can align each subtraction with the nearest addition. This is pretty straightforward when dealing with 1's.
Edit --> Dealing with values > 1.
Computing Transaction_Amount > (+/-)1 adds a little complexity, but still solvable. Now we need to stretch each addition and subtraction transaction set out by the Transaction_Amount, so the dataset is lengthened, however, the original algorithm will still be applied to a now longer dataset. This will allow for the recording of "partial fulfillments". So (12 A 5) would equate to (12 A 1), (12 A 1), (12 A 1), (12 A 1), (12 A 1). Now, when the subtractors are lengthened in similar fashion, (with all rows in the same order as the first of the sequence) the alignment will still work and addition and subtractions can be matched with the nearest neighbor(s).
DECLARE #T TABLE(Element_ID NVARCHAR(50),Element NVARCHAR(50), Transaction_Date DATETIME,Transaction_Quantity INT,Total_Inventory INT)
INSERT #T VALUES
('MO301','Make_Order','1/1/2019',5,1),
('MO302','Make_Order','1/3/2019',1,2),
('SO105','Sale','2/1/2019',-2,1),
('SO106','Sale','2/1/2019',-1,0),
('MO323','Make_Order','2/2/2019',1,1),
('SO107','Sale','2/4/2019',-1,0),
('SO191','Sale','2/5/2019',-1,-1),
('SO123','Sale','2/6/2019',-1,-2),
('SO166','Sale','3/1/2019',-1,-3),
('SO603','Sale','3/2/2019',-1,-4),
('MO400','Make_Order','3/15/2019',1,-3),
('MO459','Make_Order','3/15/2019',1,-2),
('MO460','Make_Order','3/18/2019',1,-1),
('MO491','Make_Order','3/19/2019',1,0)
;WITH Normalized AS
(
SELECT *, RowNumber = ROW_NUMBER() OVER (ORDER BY (SELECT 0)), IsAdd = CASE WHEN Transaction_Quantity>0 THEN 1 ELSE 0 END FROM #T
)
,ReplicateAmount AS
(
SELECT Element_ID, Element, Transaction_Date, Transaction_Quantity=ABS(Transaction_Quantity) ,Total_Inventory, RowNumber, IsAdd
FROM Normalized
UNION ALL
SELECT R.Element_ID, R.Element, R.Transaction_Date, Transaction_Quantity=(R.Transaction_Quantity - 1), R.Total_Inventory, R.RowNumber, R.IsAdd
FROM ReplicateAmount R INNER JOIN Normalized N ON R.RowNumber = N.RowNumber
WHERE ABS(R.Transaction_Quantity) > 1
)
,NormalizedAgain AS
(
SELECT Element_ID, Element, Transaction_Date, Transaction_Quantity=1, Total_Inventory, RowNumber = ROW_NUMBER() OVER (ORDER BY RowNumber), IsAdd FROM ReplicateAmount
)
,Additives AS
(
SELECT *, AddedOrder = ROW_NUMBER() OVER (ORDER BY (SELECT 0)) FROM NormalizedAgain WHERE IsAdd=1
)
,Subtractions AS
(
SELECT Element_ID, Element, Transaction_Date, Transaction_Quantity=-1 , Total_Inventory, RowNumber, SubtractedOrder = ROW_NUMBER() OVER (ORDER BY (SELECT 0))FROM NormalizedAgain WHERE IsAdd=0
)
,WithTies AS
(
SELECT
S.RowNumber,
S.Element_ID,
BoughtFromRowNumber = A.RowNumber,
SoldToID =S.Element_ID,
BoughFromID=A.Element_ID,
S.Element,
S.Transaction_Date,
S.Transaction_Quantity,
S.Total_Inventory
FROM
Additives A
LEFT OUTER JOIN Subtractions S ON A.AddedOrder=S.SubtractedOrder
UNION
SELECT
A.RowNumber,
A.Element_ID,
BoughtFromRowNumber = S.RowNumber,
SoldToID = NULL,
BoughFromID=NULL,
A.Element,
A.Transaction_Date,
A.Transaction_Quantity,
A.Total_Inventory
FROM
Additives A
LEFT OUTER JOIN Subtractions S ON A.AddedOrder=S.SubtractedOrder
)
SELECT
T.RowNumber,
T.Element_ID,
T.Element,
T.Transaction_Date,
T.Transaction_Quantity,
T.Total_Inventory,
T2.SoldToID,
T.BoughFromID
FROM
WithTies T
LEFT OUTER JOIN WithTies T2 ON T2.BoughtFromRowNumber= T.RowNumber
WHERE
NOT T.RowNumber IS NULL
ORDER BY
T.RowNumber
I have a table as follow :
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Design | XYZ |
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
+-------------+-----------+------+
I want to output only the groups that have unique teams greater than 3.
Only group 2 has this condition so the output is :
Expected Output:
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
+-------------+-----------+------+
not sure how to utilize this in subquery
SELECT count(Distinct(TeamName))
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
Simply put it in a Subquery:
select *
from mytable
where [GroupNumber] in
(
SELECT [GroupNumber]
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
)
Please try
SELECT *
FROM mytable where GroupNumber in (select GroupNumber
FROM mytable group by TeamName
HAVING COUNT(TeamName)>3)
I've posted several topics and every query had some problems :( Changed table and examples for better understanding
I have a table called PROD_COST with 5 fields
(ID,Duration,Cost,COST_NEXT,COST_CHANGE).
I need extra field called "groups" for aggregation.
Duration = number of days the price is valid (1 day=1row).
Cost = product price in this day.
-Cost_next = lead(cost,1,0).
Cost_change = Cost_next - Cost.
example:
+----+---------+------+-------------+-------+
|ID |Duration | Cost | Cost_change | Groups|
+----+---------+------+-------------+-------+
| 1 | 1 | 10 | -1,5 | 1 |
| 2 | 1 | 8,5 | 3,7 | 2 |
| 3 | 1 | 12.2 | 0 | 2 |
| 4 | 1 | 12.2 | -2,2 | 3 |
| 5 | 1 | 10 | 0 | 3 |
| 6 | 1 | 10 | 3.2 | 4 |
| 7 | 1 | 13.2 | -2,7 | 5 |
| 8 | 1 | 10.5 | -1,5 | 5 |
| 9 | 1 | 9 | 0 | 5 |
| 10 | 1 | 9 | 0 | 5 |
| 11 | 1 | 9 | -1 | 5 |
| 12 | 1 | 8 | 1.5 | 6 |
+----+---------+------+-------------+-------+
Now i need to group("Groups" field) by Cost_change. It can be positive,negative or 0 values.
Some kind guy advised me this query:
select id, COST_CHANGE, sum(GRP) over (order by id asc) +1
from
(
select *, case when sign(COST_CHANGE) != sign(isnull(lag(COST_CHANGE)
over (order by id asc),COST_CHANGE)) and Cost_change!=0 then 1 else 0 end as GRP
from PROD_COST
) X
But there is a problem: If there are 0 values between two positive or negative values than it groups it separately, for example:
+-------------+--------+
| Cost_change | Groups |
+-------------+--------+
| 9.262 | 5777 |
| -9.262 | 5778 |
| 9.262 | 5779 |
| 0.000 | 5779 |
| 9.608 | 5780 |
| -11.231 | 5781 |
| 10.000 | 5782 |
+-------------+--------+
I need to have:
+-------------+--------+
| Cost_change | Groups |
+-------------+--------+
| 9.262 | 5777 |
| -9.262 | 5778 |
| 9.262 | 5779 |
| 0.000 | 5779 |
| 9.608 | 5779 | -- Here
| -11.231 | 5780 |
| 10.000 | 5781 |
+-------------+--------+
In other words, if there's 0 values between two positive ot two negative values than they should be in one group, because Sequence: MINUS-0-0-MINUS - no rotation. But if i had MINUS-0-0-PLUS, than GROUPS should be 1-1-1-2, because positive valus is rotating with negative value.
Thank you for attention!
I'm Using Sql Server 2012
I think the best approach is to remove the zeros, do the calculation, and then re-insert them. So:
with pcg as (
select pc.*, min(id) over (partition by grp) as grpid
from (select pc.*,
(row_number() over (order by id) -
row_number() over (partition by sign(cost_change)
order by id
) as grp
from prod_cost pc
where cost_change <> 0
) pc
)
select pc.*, max(groups) over (order by id)
from prod_cost pc left join
(select pcg.*, dense_rank() over (order by grpid) as groups
from pcg
) pc
on pc.id = pcg.id;
The CTE assigns a group identifier based on the lowest id in the group, where the groups are bounded by actual sign changes. The subquery turns this into a number. The outer query then accumulates the maximum value, to give a value to the 0 records.