May 11, 2022 at 4:46 pm
I am trying to get the lowest cost for a part and the highest cost for a part. along with the dates that they occurred. I almost have what I want except that in my query I don't know how to associate the lowest cost with the correct date. I understand why (because that's what I told the query to do) but I am wondering how can I alter the query so that when the lowest cost is selected, it selects the corresponding date as well?
Data set example:
|Part |lowest_cost|date_received|
|--------- |--------------|-------------|
|846060| 28.373265 | 1/5/2022 |
|846060| 29.143835 | 2/28/2022 |
|846060| 27.588483 | 3/8/2022 |
|846060| 29.143835 | 4/25/2022 |
Desired output:
|Part |lowest_cost|date_received|highest_cost|last_date_received|difference|
|---------|--------------|-----------------|---------------|-----------------------|------------|
|846060| 27.588483 | 3/8/2022 | 29.143835 | 4/25/2022 | 1.555405 |
current output:
|Part |lowest_cost|date_received|highest_cost|last_date_received|difference|
|---------|--------------|-----------------|---------------|-----------------------|------------|
|846060| 27.588483 | 1/5/2022 | 29.143835 | 4/25/2022 | 1.555405 |
query I have currently:
select part,min(cost) as Lowest_Cost,max(cost) as Highest_Cost,
min(date_received) as First_date,
max(date_received) as Last_Date, (max(cost) - min(cost)) as Difference
from v_po_history
where part not like '*%' and date_received >= '2022-01-01' and date_received <= '2022-05-01' and location = 'HS' and part = '846060'
group by part
May 11, 2022 at 5:57 pm
Something like this perhaps?
declare @v_po_history table (
Part varchar(20),
Lowest_Cost dec(9,6),
Date_Received date
)
insert into @v_po_history (Part, Lowest_Cost, Date_Received)
values
('846060',28.373265,'20220105'),
('846060',29.143835,'20220228'),
('846060',27.588483,'20220308'),
('846060',29.143835,'20220425')
select distinct
Part,
lc.Lowest_Cost,
lc.Date_Received,
hc.Highest_Cost,
hc.Last_Date_Received,
hc.Highest_Cost - lc.Lowest_Cost as Difference
from @v_po_history vph
cross apply (
select top(1) Date_Received, Lowest_Cost
from @v_po_history
where Part = vph.Part
order by Lowest_Cost ASC, Date_Received ASC
) lc
cross apply (
select top(1)
Date_Received as Last_Date_Received,
Lowest_Cost as Highest_Cost
from @v_po_history
where Part = vph.Part
order by Lowest_Cost DESC, Date_Received DESC
) hc
May 11, 2022 at 6:00 pm
Here's another version.
DROP TABLE IF EXISTS #t;
CREATE TABLE #t
(
Part INT NOT NULL
,lowest_cost DECIMAL(19, 6) NOT NULL
,date_received DATE NOT NULL
);
INSERT #t
(
Part
,lowest_cost
,date_received
)
VALUES
(846060, 28.373265, '20220105')
,(846060, 29.143835, '20220228')
,(846060, 27.588483, '20220308')
,(846060, 29.143835, '20220425');
WITH ordered
AS (SELECT t.Part
,t.lowest_cost
,t.date_received
,index1 = ROW_NUMBER() OVER (PARTITION BY t.Part ORDER BY t.lowest_cost)
,index2 = ROW_NUMBER() OVER (PARTITION BY t.Part ORDER BY t.lowest_cost DESC)
FROM #t t)
SELECT o.Part
,lowest_cost = MAX(IIF(o.index1 = 1, o.lowest_cost, NULL))
,date_received = MAX(IIF(o.index1 = 1, o.date_received, NULL))
,highest_cost = MAX(IIF(o.index2 = 1, o.lowest_cost, NULL))
,last_date_received = MAX(o.date_received)
,diff = MAX(IIF(o.index2 = 1, o.lowest_cost, NULL)) - MAX(IIF(o.index1 = 1, o.lowest_cost, NULL))
FROM ordered o
--WHERE o.index1 = 1 OR o.index2 = 1
GROUP BY o.Part;
The absence of evidence is not evidence of absence
- Martin Rees
The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
- Phil Parkin
May 11, 2022 at 8:36 pm
@kaj I get a syntax error
May 11, 2022 at 8:38 pm
@phil parkin this doesn't even run. no errors or anything it just will not execute
May 11, 2022 at 8:58 pm
PSQL? Are you using postgres? You posted in a SQL Server 2019 forum.
May 11, 2022 at 9:01 pm
@ratbak hello, it's not postgres. it's called pervasive. There are no pervasive forums and since this DB engine uses SQL I figured it would be alright to post. most of the syntax is the same but I didn't know where else to go
May 11, 2022 at 9:18 pm
That's OK, but it's best to be clear about that so that volunteers know not to recommend platform-specific (TSQL) solutions.
Here's a tek-tips Pervasive forum: https://www.tek-tips.com/threadminder.cfm?pid=318
May 11, 2022 at 11:25 pm
@phil parkin this doesn't even run. no errors or anything it just will not execute
Runs fine for me. Maybe now you appreciate that different flavours of SQL have their own nuances and differences, once you go beyond the basics.
The absence of evidence is not evidence of absence
- Martin Rees
The absence of consumable DDL, sample data and desired results is, however, evidence of the absence of my response
- Phil Parkin
May 12, 2022 at 7:05 am
@kaj I get a syntax error
Okay, since we now have learned that you're using Pervasive SQL (BTrieve based) that changes things.
I don't know anything about PSQL, but looking at the error message I'm guessing that it doesn't support locally declared table variables.
I used that as a means to provide test data for the select. The table variable name was derived from your post, so try to remove the @ in the table name, and see if the select can run on its own with your table.
The basic SELECT syntax of PSQL doesn't look too different from T-SQL at a glance, but I have no chance to test anything. That'll be up to you.
I don't think I see APPLY joins in there, so that will probably also cause problems with my query.
May 12, 2022 at 11:21 am
Instead of using the apply approach you can also try a reworked query, which works wth the minimal test data you provided:
declare @v_po_history table (
Part varchar(20),
Lowest_Cost dec(9,6),
Date_Received date
)
insert into @v_po_history (Part, Lowest_Cost, Date_Received)
values
('846060',28.373265,'20220105'),
('846060',29.143835,'20220228'),
('846060',27.588483,'20220308'),
('846060',29.143835,'20220425');
with
lc as (
select top 1
Part,
Date_Received,
Lowest_Cost
from @v_po_history
order by Lowest_Cost ASC, Date_Received ASC
),
hc as (
select top 1
Part,
Date_Received as Last_Date_Received,
Lowest_Cost as Highest_Cost
from @v_po_history
order by Lowest_Cost DESC, Date_Received DESC
)
select distinct
vph.Part,
lc.Lowest_Cost,
lc.Date_Received,
hc.Highest_Cost,
hc.Last_Date_Received,
hc.Highest_Cost - lc.Lowest_Cost as Difference
from @v_po_history vph
inner join lc on lc.Part=vph.Part
inner join hc on hc.Part=vph.Part
When run on SQL Server (which is the only product I have access to), this yields the same result as my previous query that utilized the CROSS APPLY (which may not be available to you).
Part Lowest_Cost Date_Received Highest_Cost Last_Date_Received Difference
-------------------- ------------------------------ ------------- ------------------------------ ------------------ ------------------------------
846060 27.588483 2022-03-08 29.143835 2022-04-25 1.555352
(1 row affected)
I have left the declared table variable with testdata for my own convenience, but you'll probably have to remove the @ from the table name and only concern yourself with the query itself.
May 12, 2022 at 5:07 pm
Instead of using the apply approach you can also try a reworked query, which works wth the minimal test data you provided:
declare @v_po_history table (
Part varchar(20),
Lowest_Cost dec(9,6),
Date_Received date
)
insert into @v_po_history (Part, Lowest_Cost, Date_Received)
values
('846060',28.373265,'20220105'),
('846060',29.143835,'20220228'),
('846060',27.588483,'20220308'),
('846060',29.143835,'20220425');
with
lc as (
select top 1
Part,
Date_Received,
Lowest_Cost
from @v_po_history
order by Lowest_Cost ASC, Date_Received ASC
),
hc as (
select top 1
Part,
Date_Received as Last_Date_Received,
Lowest_Cost as Highest_Cost
from @v_po_history
order by Lowest_Cost DESC, Date_Received DESC
)
select distinct
vph.Part,
lc.Lowest_Cost,
lc.Date_Received,
hc.Highest_Cost,
hc.Last_Date_Received,
hc.Highest_Cost - lc.Lowest_Cost as Difference
from @v_po_history vph
inner join lc on lc.Part=vph.Part
inner join hc on hc.Part=vph.PartWhen run on SQL Server (which is the only product I have access to), this yields the same result as my previous query that utilized the CROSS APPLY (which may not be available to you).
Part Lowest_Cost Date_Received Highest_Cost Last_Date_Received Difference
-------------------- ------------------------------ ------------- ------------------------------ ------------------ ------------------------------
846060 27.588483 2022-03-08 29.143835 2022-04-25 1.555352
(1 row affected)I have left the declared table variable with testdata for my own convenience, but you'll probably have to remove the @ from the table name and only concern yourself with the query itself.
This query will only work if there is exactly one part. I added one more record for a different part, and now I am getting no records at all.
insert into @v_po_history (Part, Lowest_Cost, Date_Received)
values
('846060',28.373265,'20220105'),
('846060',29.143835,'20220228'),
('846060',27.588483,'20220308'),
('846060',29.143835,'20220425'),
('847070',29.154827,'20220425'); -- new record
Drew
J. Drew Allen
Business Intelligence Analyst
Philadelphia, PA
May 12, 2022 at 5:54 pm
This query will only work if there is exactly one part. I added one more record for a different part, and now I am getting no records at all.
insert into @v_po_history (Part, Lowest_Cost, Date_Received)
values
('846060',28.373265,'20220105'),
('846060',29.143835,'20220228'),
('846060',27.588483,'20220308'),
('846060',29.143835,'20220425'),
('847070',29.154827,'20220425'); -- new recordDrew
Yes, that was sloppy of me. I should have checked that it would work with more data! 🙁
I guess that leaves us with the unwieldy subquery version:
with
base as (
select distinct
Part
from @v_po_history
),
base_LHC as (
select
base.Part,
(select top 1 Lowest_Cost from @v_po_history where Part=base.Part order by Lowest_Cost ASC, Date_Received ASC) AS Lowest_Cost,
(select top 1 Date_Received from @v_po_history where Part=base.Part order by Lowest_Cost ASC, Date_Received ASC) AS Date_Received,
(select top 1 Lowest_Cost from @v_po_history where Part=base.Part order by Lowest_Cost DESC, Date_Received ASC) AS Highest_Cost,
(select top 1 Date_Received from @v_po_history where Part=base.Part order by Lowest_Cost DESC, Date_Received ASC) AS Last_Date_Received
from base
)
select
Part,
Lowest_Cost,
Date_Received,
Highest_Cost,
Last_Date_Received,
Highest_Cost - Lowest_Cost as Difference
from base_LHC;
This at least does produce a better result:
Part Lowest_Cost Date_Received Highest_Cost Last_Date_Received Difference
-------------------- ------------------------------ ------------- ------------------------------ ------------------ ------------------------------
846060 27.588483 2022-03-08 29.143835 2022-02-28 1.555352
847070 29.154827 2022-04-25 29.154827 2022-04-25 0.000000
(2 rows affected)
May 12, 2022 at 7:49 pm
I am trying to get the lowest cost for a part and the highest cost for a part. along with the dates that they occurred. I almost have what I want except that in my query I don't know how to associate the lowest cost with the correct date. I understand why (because that's what I told the query to do) but I am wondering how can I alter the query so that when the lowest cost is selected, it selects the corresponding date as well?
Data set example:
|Part |lowest_cost|date_received| |--------- |--------------|-------------| |846060| 28.373265 | 1/5/2022 | |846060| 29.143835 | 2/28/2022 | |846060| 27.588483 | 3/8/2022 | |846060| 29.143835 | 4/25/2022 |
Desired output:
|Part |lowest_cost|date_received|highest_cost|last_date_received|difference| |---------|--------------|-----------------|---------------|-----------------------|------------| |846060| 27.588483 | 3/8/2022 | 29.143835 | 4/25/2022 | 1.555405 |
current output:
|Part |lowest_cost|date_received|highest_cost|last_date_received|difference| |---------|--------------|-----------------|---------------|-----------------------|------------| |846060| 27.588483 | 1/5/2022 | 29.143835 | 4/25/2022 | 1.555405 |
query I have currently:
select part,min(cost) as Lowest_Cost,max(cost) as Highest_Cost, min(date_received) as First_date, max(date_received) as Last_Date, (max(cost) - min(cost)) as Difference from v_po_history where part not like '*%' and date_received >= '2022-01-01' and date_received <= '2022-05-01' and location = 'HS' and part = '846060' group by part
Please read the article at the first link in my signature line below for future posts. Thanks.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 14 posts - 1 through 13 (of 13 total)
You must be logged in to reply to this topic. Login to reply