Trim results of an SQL query to only the earliest dates - sql

I have a query that filters for two different value possibilities for a column - STM and RMC. Meaning, my query will return a table that either has RMC or STM in the "TYPE" column. Something that looks like this:
NAME ACCT TYPE AMT DATE
ABBOTT 1234 STM 09/01/2022
ABBOTT 1234 STM 10/05/2022
ABBOTT 1234 STM 11/03/2022
ABBOT 1234 RMC 25.00
What I would like to do is limit those STM results so that I only get the earliest date back. Something like this:
NAME ACCT TYPE AMT DATE
ABBOTT 1234 STM 09/01/2022
ABBOT 1234 RMC 25.00
I've tried something like this:
SELECT
NAME,
ACCT,
TYPE,
CODE,
AMT,
DT
FROM
table1
WHERE
DT BETWEEN '09/01/2022 00:0:0' AND '12/31/2022 00:0:0'
GROUP BY
NAME,
ACCT,
TYPE,
DT
HAVING
TYPE= 'STM' AND
DT= MIN(table1.DT) OR
TYPE= 'RMC' AND
CODE= '1-PR' OR
CODE= '2-PR'
ORDER BY NAME, ACCT, DT
This doesn't do anything however. It runs, but shows all results for all dates within that time period. Problem is, I think the MIN() function just runs on the specific line, not the group of results that make up the rows that have STM in the TYPE column. So it's not really calculating what the earliest date is of that set.

Related

SQLite how to get average values of available offers in a time frame

Sorry for the title, because it's all but self-explanatory.
So I have a database which is daily populated with used car offers, each one having as columns: price, in_date (day when an offer was registered) and exit_date (day when an offer ceases to exist, defaulting to 'Null' otherwise). Note that no longer available offers stay on the database, with their corresponding 'exit_date'.
What I need:
I'd like to SELECT the average price of offers available on each possible 'in_date' existing in the database:
in_date | avg price
-------------------------
2018-05-27 | 8157
2018-05-29 | 8240
2018-06-01 | 8199
2018-06-02 | 8220
The problem is that I need to compare in_date for each row with in_date and exit_date in the rest of the rows, and I have no clue how to do that.
Trying to express this into some code:
SELECT
in_date**,
(SELECT avg(price) FROM offers WHERE in_date** > in_date and exit_date > in_date** or exit_date is null)
from oferted
GROUP by in_date**
in_date** being a 'fixed' in_date value for each row to compare the in_date and exit_date of the rest of the rows to.
thanks.
You are pretty close. You can do this using a subquery in the from to get the in dates -- and then qualify the column names:
SELECT d.in_date,
(SELECT avg(o.price)
FROM offers o
WHERE d.in_date > o.in_date and
(o.exit_date > d.in_date or exit_date is null)
)
FROM (SELECT DISTINCT in_date
FROM offsets
) d;

SQL Pattern to select only first row from a group

I have a table which has a large number of entries and from which I need only the first in each group.
The table is used to store daily fund prices (1000+ funds) over the last 30 years. I need to find the last price prior to, or on a specific date for each fund existing on that date (so only one row per fund).
In its simplified form, the table has columns Date, FundCode and Price.
The following input
Date FundCode Price
2016/01/05 X123 1.234
2016/01/04 X123 1.233
2016/01/03 X123 1.222
2016/01/05 A456 1.876
2016/01/04 A456 1.822
2016/01/03 A456 1.776
2016/01/03 M234 3.234
...when queried for 2016/01/04, should produce
Date FundCode Price
2016/01/04 X123 1.233
2016/01/04 A456 1.822
2016/01/03 M234 3.234
I have a solution which uses a correlated subquery in the where but no amount of messing with indexes will make it run in a reasonable amount of time.
I'm sure there's a straightforward solution to this but I just can't see it.
Somethink like
SELECT fundCode, price, date FROM your_table WHERE date<='date_you_need' GROUP BY fundCode HAVING MAX(date)
Query like this works in SQLITE, what db do you use?
A single nested query gives me the max date for each fund, then inner join to this on fundCode/Date, thus...
SELECT
Date,
FundCode,
Price
FROM
PriceHistory H
INNER JOIN
/* this nested query gives the max date for each fund*/
(SELECT
FundCode,
max(Date) AS MaxDate
FROM
PriceHistory H2
WHERE
Date<=#DateToSearchFor
GROUP BY
FundCode) AS RowSelector
ON H.FundCode=RowSelector.FundCode AND H.Date=RowSelector.MaxDate

Select most current data in grouped set in Oracle

I am writing a procedure to query some data in Oracle and grouping it:
Account Amt Due Last payment Last Payment Date (mm/dd/yyyy format)
1234 10.00 5.00 12/12/2013
1234 35.00 8.00 12/12/2013
3293 15.00 10.00 11/18/2013
4455 8.00 3.00 5/23/2013
4455 14.00 5.00 10/18/2013
I want to group the data, so there is one record per account, the Amt due is summed, as well as the last payment. Unless the last payment date is different -- if the date is different, then I just want the last payment. So I would want to have a result of something like this:
Account Amt Due Last payment Last Payment Date
1234 45.00 13.00 12/12/2013
3293 15.00 10.00 11/18/2013
4455 22.00 5.00 10/18/2013
I was doing something like
select Account, sum (AmtDue), sum (LastPmt), Max (LastPmtDt)
from all my tables
group by Account
But, that doesn't work for the last record above, because the last payment was only the $5.00 on 10/18, not the sum of them on 10/18.
If I group by Account and LastPmtDt, then I get two records for the last, but I only want one per account.
I have other data I'm querying, and I'm using a CASE, INSTR, and LISTAGG on another field (if combining them gives me this substring and that, then output 'Both'; else if it only gives me this substring, then output the substring; else if it only gives me the other substring, then output that one). It seems like I may need something similar, but not by looking for a specific date. If the dates are the same, then sum (LastPmt) and max (LastPmtDt) works fine, if they are not the same, then I want to ignore all but the most recent LastPmt and LastPmtDt record(s).
Oh, and my LastPmt and LastPmtDt fields are already case statements within the select. They aren't fields that I already can just access. I'm reading other posts about RANK and KEEP, but to involve both fields, I'd need all that calculation of each field as well. Would it be more efficient to query everything, and then wrap another query around that to do the grouping, summing, and selecting fields I want?
Related: HAVING - GROUP BY to get the latest record
Can someone provide some direction on how to solve this?
Try this:
select Account,
sum ( Amt_Due),
sum (CASE WHEN Last_Payment_Date = last_dat THEN Last_payment ELSE 0 END),
Max (Last_Payment_Date)
from (
SELECT t.*,
max( Last_Payment_Date ) OVER( partition by Account ) last_dat
FROM table1 t
)
group by Account
Demo --> http://www.sqlfiddle.com/#!4/fc650/8
Rank is the right idea.
Try this
select a.Account, a.AmtDue, a.LastPmt, a.LastPmtDt from (
select Account, sum (AmtDue) AmtDue, sum (LastPmt) LastPmt, LastPmtDt,
RANK() OVER (PARTITION BY Account ORDER BY LastPmtDt desc) as rnk
from all my tables
group by Account, LastPmtDt
) a
where a.rnk = 1
I haven't tested this, but it should give you the right idea.
Try this:
select Account, sum(AmtDue), sum(LastPmt), LastPmtDt
from (select Account,
AmtDue,
LastPmt,
LastPmtDt,
max(LastPmtDt) over(partition by Account) MaxLastPmtDt
from your_table) t
where t.LastPmtDt = t.MaxLastPmtDt
group by Account, LastPmtDt

Access 2007 Transform transactional table to summary

I have a transaction style table in Access 2007. For example
ID Start Date End Date Type Sub Type
1 1/01/2012 15/02/2012 Supermarket Bread
1 16/02/2012 20/03/2012 Supermarket Milk
1 21/03/2012 30/09/2012 Supermarket Cheese
1 1/11/2012 15/11/2013 Hardware Nails
Want I need to do is transform this into this:
ID Start Date End Date Type
1 1/01/2012 30/09/2012 Supermarket
1 1/11/2012 15/11/2013 Hardware
A single record per ID with the start date from the first 'supermarket' record through to the last 'supermarket' record.
Appreciate any suggestions/help with if this is possible in Access.
It looks like you want an aggregate query which groups by ID and Type. You can then use Min() and Max() to retrieve the earliest Start Date and the latest End Date within each group.
SELECT
ID,
[Type],
Min([Start Date]) AS start_date,
Max([End Date]) AS end_date
FROM YourTable
GROUP BY
ID,
[Type];

Finding StartDate,EndDate from overriding StartDates

I have two tables with the following (simplified) structures:
table "Factors" which holds data about purchased goods' factors and has these columns:
FactorSerial, PurchaseDate, PurchasedGood
table "Prices" which holds goods prices on different dates
Serial, GoodCode, EvaluationDate, Price
A price is valid until a new row with the same Code but different date is added and thus updates its value
Now, I want to create a table which adds the price to the table 1 according to purchase date.
So if we have:
PurchaseDate PurchasedGood
-----------------------------
05/20/2011 A111
and:
GoodCode EvaluationDate Price
--------------------------------
A111 02/01/2011 100
...
A111 04/01/2011 110
...
A111 06/01/2011 120
the result would be
PurchaseDate PurchasedGood Price
-----------------------------------
05/20/2011 A111 110
Preferred method is creating the view Prices1 as
Serial GoodCode StartDate EndDate Price
and then joining Factors with this view by
PurchasedDate between StartDate AND EndDate
Can anybody show me how to create view1 (or obtaining the final result with any other method)? Thanks in advance!
P.S. sorry for my bad English!
I want to create a table which adds the price to the table 1 according to purchase date.
Here is a query that returns such data. The syntax is pretty standard SQL, I believe, but this was tested on SQL Server (looks like you may be using PostgreSQL with your "serial" naming).
select a.FactorSerial, a.PurchasedGood, a.PurchaseDate
, (select max(Price) from Prices where GoodCode = a.PurchasedGood and EvaluationDate = a.EvaluationDate) as Price
from (
select f.FactorSerial, f.PurchasedGood, f.PurchaseDate, max(p.EvaluationDate) as EvaluationDate
from Factors as f
join Prices as p on f.PurchasedGood = p.GoodCode
where f.PurchaseDate >= p.EvaluationDate
group by f.FactorSerial, f.PurchasedGood, f.PurchaseDate
) as a
This query assumes that there are no Purchases before a Price existed.
Also, considering:
Preferred method is creating the view Prices1 as
Serial GoodCode StartDate EndDate Price
and then joining Factors with this view by
PurchasedDate between StartDate AND EndDate
between is inclusive. Using this method that you've described, you would get duplicates if a PurchaseDate lies on the EndDate of one row and the StartDate of another.