I have this query calculating how many products I have to produce to serve my pending orders and the components I need to produce them.
select
l.codart as SKU, --final product
e.codartc as Component, --piece of final product
e.unicompo, --Components needed for each SKU
l1.SKU_pending - s.SKU_STOCK as "SKU to produce",
s2.C_STOCK as "Component stock",
s2.C_STOCK - sum((l1.SKU_pending - s.SKU_STOCK) * e.unicompo)
over (partition by e.codartc order by l.codart) as "Component stock after producing"
from linepedi l --table with sales orders
left join escandallo e on e.codartp = l.codart --table with SKU components
inner join (select l1.codart, sum(l1.unidades - l1.uniservida - l1.unianulada) as "SKU_pending" --pending sales. I called it from a subquery so I don't have to repeat the calculation each time I need it
from linepedi l1
where (l1.unidades - l1.uniservida - l1.unianulada) > 0
group by l1.codart) l1 on l1.CODART = l.codart
left join (select s.codart, sum(s.unidades) as "SKU_STOCK"
from __STOCKALMART s
group by s.codart) s on s.codart = l.codart
left join (select s.codart, sum(s.unidades) as "C_STOCK"
from __STOCKALMART s
group by s.codart) s2 on s2.codart = e.codartc
where l1.SKU_pending - s.SKU_STOCK > 0
group by l.codart, e.codartc, e.unicompo, l1.SKU_pending, s.SKU_STOCK, s2.C_STOCK
order by l.codart
Query returns next table:
SKU
Component
unicompo
SKU to produce
Component stock
Component stock after producing
20611
286
1
50
2021
1971
20611
329
1
50
2759
2709
20611
ARTZD031
1
50
643
593
220178
ARTZD027
1
384
477
93
220178
SICBB005
1
384
845
461
220178
265
1
384
894
510
220185
265
1
200
894
310
220185
SICBB005
1
200
845
261
220185
ARTZD028
1
200
71
-129
220192
ARTZD029
1
200
364
164
220192
SICBB005
1
200
845
61
220192
265
1
200
894
110
When Component stock after producing returns less than 0, I don't want it to substract the SKU to produce, but the mininum Component stock for that SKU, while "saving" this value for the next time I need the same component. I think I would need to make an iteration with conditionals.
This is what I'd like to accomplish:
SKU
Component
unicompo
SKU to produce
Component stock
Component stock after producing
20611
286
1
50
2021
1971
20611
329
1
50
2759
2709
20611
ARTZD031
1
50
643
593
220178
ARTZD027
1
384
477
93
220178
SICBB005
1
384
845
461
220178
265
1
384
894
510
220185
265
1
200
894
439
220185
SICBB005
1
200
845
390
220185
ARTZD028
1
200
71
0
220192
ARTZD029
1
200
364
164
220192
SICBB005
1
200
845
190
220192
265
1
200
894
239
I've been reading some articles and I feel like it might be done with a recursive CTE, but I don't really know how since I didn't find any example similar to mine.
How can achieve this? Any help will be appreciated. Thank you very much
I have two tables A and B,
Table A
PstngDate WorkingDayOutput
12/1/2020 221
12/3/2020 327
12/4/2020 509
12/5/2020 418
12/7/2020 390
12/8/2020 431
12/9/2020 244
12/10/2020 246
12/11/2020 314
12/12/2020 301
12/14/2020 411
12/15/2020 530
12/16/2020 554
12/17/2020 300
12/18/2020 375
12/23/2020 402
12/24/2020 302
12/25/2020 269
12/26/2020 382
12/28/2020 608
Table B
PstngDate HolidayOutput isWorkingDay
12/2/2020 20 0
12/6/2020 24 0
12/13/2020 31 0
12/19/2020 82 0
12/22/2020 507 0
12/27/2020 537 0
Expected output:
PstngDate WorkingDayOutput HolidayOutput
12/1/2020 221 20
12/3/2020 327
12/4/2020 509
12/5/2020 418 24
12/7/2020 390
12/8/2020 431
12/9/2020 244
12/10/2020 246
12/11/2020 314
12/12/2020 301 31
12/14/2020 411
12/15/2020 530
12/16/2020 554
12/17/2020 300
12/18/2020 375 589
12/23/2020 402
12/24/2020 302
12/25/2020 269
12/26/2020 382 537
12/28/2020 608
I want to join TableB to TableA with nearest lesser date column. If you see Expectedoutput table, day 18 row of holidayoutput column is taking sum of day19 and day22 of table B.
I want to join TableB to TableA with nearest lesser date column
This sounds like a lateral join:
select a.*, coalesce(b.holidayquantity, 0) as holidayquantity
from a
outer apply (
select top (1) b.*
from b
where b.pstng_date >= a.pstng_date
order by b.pstng_date
) b
You can use self left join as follows:
Select pstng_date, workingDayQuantity,
HolidayQuantity,
workingDayQuantity + HolidayQuantity as total
From
(Select a.*, b.HolidayQuantity,
Row_number() over (partirion by a.psrng_date order by b.pstng_date) ad rn
From tablea a join tableb b On b.pstng_date > a.pstng_date) t
Where rn=1
So basically I have some simple SQL code that looks like the following;
SELECT
[Column1]
,[Column2]
,[Column3]
,[Column4]
,MIN([Column5]) AS maxColumn5
,MAX([Column6]) AS minColumn6
,SUM([Column7]) AS sumColumn7
,SUM([Column8]) AS sumColumn8
,SUM([Column9]) AS sumColumn9
FROM
[tableName]
GROUP BY
[Column1]
,[Column2]
,[Column3]
,[Column4]
What I am trying to do is also find the column either 'Column1', 'Column2', or 'Column3' that corresponds to the MIN([Column6]) and then the column that corresponds to MAX([Column8]).
The output should be exactly the same except there will be an extra 2 column at the end specifying which one the min and max are associated with.
I think there is a simple problem in your question, as Col1,Col2,Col3 that correspond to the max or min, are displayed directly, in other words you have them as you are grouping by Col1,Col2,Col3 & Col4.
As you did not provide some data, I will set some random data to prove my point.
Lets create a memory table similar to yours with 9 columns and fill it with random data for col6-8 with 10 rows for example, you can use the below:-
Declare #data Table(
Column1 int,Column2 int,Column3 int,Column4 int,Column5 int,Column6 int,Column7 int,Column8 int,Column9 int
)
declare #index int=5
while(#index>0)
begin
insert into #data values(1,2,3,4,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000)
insert into #data values(5,6,7,8,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000)
set #index=#index-1
end
we can see the data with the below
select * from #data order BY [Column1],[Column2],[Column3],[Column4]
Column1 Column2 Column3 Column4 Column5 Column6 Column7 Column8 Column9
1 2 3 4 669 203 278 364 577
1 2 3 4 389 316 290 548 661
1 2 3 4 835 555 942 985 604
1 2 3 4 477 743 580 305 414
1 2 3 4 431 296 471 150 352
1 2 3 4 346 220 573 941 633
1 2 3 4 392 450 652 978 883
1 2 3 4 235 479 751 136 978
1 2 3 4 906 183 141 915 783
1 2 3 4 329 342 682 977 870
5 6 7 8 218 740 41 299 816
5 6 7 8 800 630 674 888 799
5 6 7 8 27 307 446 743 345
5 6 7 8 501 928 824 592 691
5 6 7 8 439 624 260 757 547
5 6 7 8 287 610 287 708 652
5 6 7 8 441 711 433 642 343
5 6 7 8 751 928 237 53 535
5 6 7 8 594 768 708 173 33
5 6 7 8 352 703 943 867 661
now lets see the result of your grouping that you provided without any change
Col1 Col2 Col3 Col4 minCol5 maxCol6 maxCol8 sumCol7 sumCol8 sumCol9
1 2 3 4 235 743 985 5360 6299 6755
5 6 7 8 27 928 888 4853 5722 5422
so if we go back to your question, what is the value of Col1,Col2,Col3 for the maxCol6, well for each maxCol6 you have the values of Col1,Col2,Col3 & even Col4.
so what are the values for Col1,Col2,Col3 for maxCol16 that is 928, well they are 5,6 & 7.
ok, now lets say you want the record key that have that maxCol6, that is easy too, we would add an identity col as ID as below:-
Declare #data Table(
ID int identity(1,1), Column1 int,Column2 int,Column3 int,Column4 int,Column5 int,Column6 int,Column7 int,Column8 int,Column9 int
)
declare #index int=10
while(#index>0)
begin
insert into #data values(1,2,3,4,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000)
insert into #data values(5,6,7,8,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000,RAND()*1000)
set #index=#index-1
end
select * from #data order BY [Column1],[Column2],[Column3],[Column4]
;with agg as (
SELECT
[Column1]
,[Column2]
,[Column3]
,[Column4]
,MIN([Column5]) AS minColumn5
,MAX([Column6]) AS maxColumn6
,MAX([Column8]) AS maxColumn8
,SUM([Column7]) AS sumColumn7
,SUM([Column8]) AS sumColumn8
,SUM([Column9]) AS sumColumn9
FROM
#data [tableName]
GROUP BY
[Column1]
,[Column2]
,[Column3]
,[Column4]
)
--select * from agg order BY [Column1],[Column2],[Column3],[Column4]
select agg.*,maxCol6.ID [MaxCol6Seq],maxCol8.ID [MaxCol8Seq] from agg
inner join #data maxCol6
on agg.Column1=maxCol6.Column1
and agg.Column2=maxCol6.Column2
and agg.Column3=maxCol6.Column3
and agg.Column4=maxCol6.Column4
and agg.maxColumn6=maxCol6.Column6
inner join #data maxCol8
on agg.Column1=maxCol8.Column1
and agg.Column2=maxCol8.Column2
and agg.Column3=maxCol8.Column3
and agg.Column4=maxCol8.Column4
and agg.maxColumn8=maxCol8.Column8
As this is a new run for this set of data , below:-
ID Column1 Column2 Column3 Column4 Column5 Column6 Column7 Column8 Column9
1 1 2 3 4 201 848 993 50 304
3 1 2 3 4 497 207 644 399 104
5 1 2 3 4 445 321 822 151 185
7 1 2 3 4 611 402 620 61 543
9 1 2 3 4 460 409 182 915 211
11 1 2 3 4 886 804 180 213 282
13 1 2 3 4 614 709 932 806 162
15 1 2 3 4 795 752 110 474 463
17 1 2 3 4 737 545 77 648 727
19 1 2 3 4 788 862 266 464 851
20 5 6 7 8 218 561 943 572 54
18 5 6 7 8 741 621 610 214 536
16 5 6 7 8 579 248 374 693 761
14 5 6 7 8 866 415 198 528 657
12 5 6 7 8 905 947 500 50 387
10 5 6 7 8 492 860 948 299 220
8 5 6 7 8 861 328 727 40 327
6 5 6 7 8 435 534 707 769 777
4 5 6 7 8 587 68 45 184 614
2 5 6 7 8 189 24 289 121 772
The result is as below:-
C1 C2 C3 C4 minC5 maxC6 maxC8 sumC7 sumC8 sumC9 MaxCol6Seq MaxCol8Seq
1 2 3 4 201 862 915 4826 4181 3832 19 9
5 6 7 8 189 947 769 5341 3470 5105 12 6
Hope this helps.
If you just want a flag on each row specifying whether the value is the overall maximum or minimum, you can use window functions and CASE:
SELECT [Column1], [Column2], [Column3], [Column4],
MAX([Column5]) AS maxColumn5,
MIN([Column6]) AS minColumn6,
SUM([Column7]) AS sumColumn7,
SUM([Column8]) AS sumColumn8,
SUM([Column9]) AS sumColumn9,
(CASE WHEN MIN([Column6]) = MIN(MIN([Column6])) OVER () THEN 1 ELSE 0 END) as is_min_column6,
(CASE WHEN MAX([Column7]) = MAX(MAX([Column7])) OVER () THEN 1 ELSE 0 END) as is_max_column7
FROM [tableName]
GROUP BY [Column1], [Column2], [Column3], [Column4]
I need to count rows based on 2 fields for grouping.
Animals (a)
id group_id strain_id death_date death_cause status
-----------------------------------------------------------------------
1 512 164 2015-12-01 Culled P
2 512 164 2015-12-02 Culled A
3 512 164 2015-12-02 Surplus B
4 512 230 2015-12-06 Culled A
5 512 164 2015-12-28 Culled A
6 512 230 2016-01-20 Culled B
7 512 230 2016-01-20 Surplus P
8 512 164 NULL NULL P
9 512 230 NULL NULL B
10 512 230 NULL NULL A
11 512 164 2016-01-25 Culled B
12 512 164 2016-02-29 Culled A
13 512 230 2016-02-03 Surplus P
14 512 230 2016-02-03 Culled A
Groups (g)
id group_name
--------------
512 Mice
Strain (s)
id strain_name
----------------
164 Strain 1
230 Strain 2
Group Animal Count (gac)
id total_animals alive_count dead_count
----------------------------------------------------------------------
512 14 3 11
Mating History (mh)
id animal_id history_type history_date
--------------------------------------------------------
1001 2 MA 2015-11-20
1002 2 MR 2015-12-01
1003 3 MA 2015-12-01
1004 6 FA 2015-12-21
1005 9 FA 2016-02-07
1006 10 MA 2016-01-27
1007 11 FA 2015-12-12
So when I group them by the strain_id and the death_cause this is what they should look like visually:
Strain 1 ---- Culled
1 512 164 2015-12-01 Culled P
2 512 164 2015-12-02 Culled A
5 512 164 2015-12-28 Culled A
11 512 164 2016-01-25 Culled B
12 512 164 2016-02-29 Culled A
Strain 1 ---- Surplus
3 512 164 2015-12-02 Surplus B
Strain 2 ---- Culled
4 512 230 2015-12-06 Culled A
6 512 230 2016-01-20 Culled B
14 512 230 2016-02-03 Culled A
Strain 2 ---- Surplus
7 512 230 2016-01-20 Surplus P
13 512 230 2016-02-03 Surplus P
What I want to get from the SQL query is the following result:
g_name s_name d_cause a_total c_alive c_dead c_pup c_breeder c_total
------------------------------------------------------------------------------
Mice Strain 1 Culled 12 3 9 1 2 5
Mice Strain 1 Surplus 12 3 9 0 1 1
Mice Strain 2 Culled 12 3 9 0 1 3
Mice Strain 2 Surplus 12 3 9 2 0 2
Basically I want to count the number of animals using 2 categories which in this case is the strain_name and the death_cause
Note that for an animal to be counted as a breeder (c_breeder), I have to look at the Mating History table and check if the animal_id has ever had any of these codes MA or FA.
I am using INNER JOIN on the groups, group_animal_count, and strains. I use LEFT JOIN for mating_history since animals with a status of P won't have records in that table since they're just pups and won't be involved with mating.
Try:
SELECT group_name, strain_name,death_cause, count(*) as Total
FROM ANIMALS a
JOIN GROUPS g ON a.group_id = g.id
JOIN STRAIN s ON a.strain_id = s.id
GROUP BY group_name, strain_name,death_cause
You can do the aggregation before joining the tables:
SELECT group_name, strain_name, death_cause, total
FROM (
SELECT group_id,
strain_id,
death_cause,
COUNT(*) AS total
FROM animals
GROUP BY group_id, strain_id, death_cause
) a
INNER JOIN groups g ON ( g.group_id = a.group_id )
INNER JOIN strain s ON ( s.strain_id = a.strain_id );
Well after much messing about I have finally got a query that gives sales totals of all the products, and another that gives stock absorbed for all of the products, (images below).
I was looking at Allen Brown's stuff and I get it, but I was wondering If i could make a summary report covering all of the available stock for all of the products. there are 31 products in total and they all appear in the stock query and in the sales query.
http://imageshack.us/photo/my-images/810/87887.jpg
http://imageshack.us/photo/my-images/827/8787j.jpg
Any Ideas on the coding to use...
I guess it would be possible to do, but then I don't really know where to start
I really want to make a report which will summarise the stock of each of the products in the queries.
Instead of having a button for working the stock of one specific product, having a button that will work the stock for each of the products in the queries at the same time.
does this make sense?
Thanks
Sam
UPDATE
this is the query for finding stock
SELECT TblStock.ProductID, Sum(TblStock.StockLevel) AS Stock, TblProduct.Item
FROM TblStock INNER JOIN TblProduct ON TblStock.ProductID = TblProduct.ProductID
GROUP BY TblStock.ProductID, TblProduct.Item;
this is the query for finding quantity of sales
SELECT TblProduct.Item, Sum(TblTotalSale.Size) AS Quantity, TblProduct.ProductID
FROM TblProduct INNER JOIN TblTotalSale ON TblProduct.[ProductID] = TblTotalSale.[ProductID]
GROUP BY TblProduct.Item, TblProduct.ProductID;
TblStock looks like
StockID ProductID StockLevel
89 32 200
90 33 72
91 34 72
92 1 528
93 3 528
94 5 528
95 9 528
96 7 528
97 18 80
98 30 72
99 31 204
Product Table looks like
ProductID Item Price StockDelivery PriceSmall Large Small
1 Carling £2.50 528 £1.40 2 1
3 Carlsburg £2.70 528 £1.60 2 1
5 IPA £2.30 528 £1.20 2 1
7 StrongBow £2.80 528 £1.65 2 1
9 RevJames £2.45 528 £1.30 2 1
11 Becks £2.90 72 1
12 WKDBlue £2.80 72 1
13 WKDRed £2.80 72 1
14 SmirnoffIce £2.80 72 1
15 KoppaburgPear £3.10 72 1
16 KoppaburgSum £3.10 72 1
17 Bulmers £2.90 72 1
18 Vodka £1.60 80 1
19 Gin £1.40 80 1
20 Sherry £1.40 80 1
21 Sambuca £1.70 80 1
22 Rum £1.60 80 1
23 Port £1.60 80 1
24 Whiskey £1.60 80 1
25 Baileys £1.60 80 1
26 Jagermeister £1.50 80 1
27 Martini £1.60 80 1
28 CokeCan £0.85 72 1
29 Coke £1.30 204 £0.30 2 1
30 LemonadeCan £0.85 72 1
31 Lemonade £1.30 204 £0.30 2 1
32 Squash £0.25 200 1
33 Tonic £0.85 72 1
34 RedBull £1.90 72 1
35 Nuts £0.60 70 1
36 Crisps £0.60 70 1
tbltotalSale looks like
TotalSalesID ProductID SalePrice Day Time Size
370 1 £2.50 05/02/2012 19:53:14 2
371 1 £1.40 05/02/2012 19:53:14 1
372 1 £2.50 05/02/2012 19:53:14 2
373 1 £1.40 05/02/2012 19:53:14 1
374 1 £2.50 05/02/2012 20:25:12 2
375 1 £1.40 05/02/2012 20:25:12 1
376 1 £2.50 05/02/2012 20:25:12 2
377 1 £1.40 05/02/2012 20:25:12 1
378 1 £2.50 05/02/2012 20:25:12 2
379 1 £2.50 05/02/2012 20:25:12 2
380 1 £1.40 05/02/2012 20:25:12 1
381 5 £2.30 05/02/2012 20:25:12 2
382 5 £2.30 05/02/2012 20:25:12 2
383 5 £1.20 05/02/2012 20:25:12 1
384 7 £2.80 05/02/2012 20:25:12 2
385 7 £1.65 05/02/2012 20:25:12 1
386 7 £1.65 05/02/2012 20:25:12 1
387 9 £1.30 05/02/2012 20:25:12 1
435 11 £2.90 05/02/2012 20:25:12 1
436 11 £2.90 05/02/2012 20:42:49 1
437 11 £2.90 05/02/2012 20:42:49 1
I can upload my database if that would be easyer.
have tried to use the following Query for what i want, but it returns 11 results for each product id and none that are correct....
SELECT QrySaleTot.Item, QrySaleTot.ProductID, [QryStockLevel].[Stock]-[QrySaleTot].[Quantity] AS StockOnHand
FROM QrySaleTot, QryStockLevel
GROUP BY QrySaleTot.Item, QrySaleTot.ProductID, [QryStockLevel].[Stock]-[QrySaleTot].[Quantity];
Thanks
You can join the two tables by id and just subtract.
SELECT Sales.ID, Stock.Level - Sales.Quantity
FROM Sales
INNER JOIN Stock
ON Sales.ID = Stock.ID
Updating is not so different. Play around with the query design window. You may wish to read:
Fundamental Microsoft Jet SQL for Access 2000
Intermediate Microsoft Jet SQL for Access 2000
Advanced Microsoft Jet SQL for Access 2000
You included this query in the update to your question:
SELECT
QrySaleTot.Item,
QrySaleTot.ProductID,
[QryStockLevel].[Stock]-[QrySaleTot].[Quantity] AS StockOnHand
FROM QrySaleTot, QryStockLevel
GROUP BY
QrySaleTot.Item,
QrySaleTot.ProductID,
[QryStockLevel].[Stock]-[QrySaleTot].[Quantity];
The first problem is you don't have a join condition ... so each row from QrySaleTot will be matched up with every row from QryStockLevel. That will produce what is called a Cartesian product, or cross join. Revise it to use a join on a field the 2 queries have in common.
The GROUP BY doesn't seem useful here because you're not computing any aggregate values.
Finally, Item is a reserved word. If you must keep that field name, bracket it everywhere you reference it in your queries like this: QrySaleTot.[Item]