Access SQL - Get last available value - sql

scenario:
Table 1 (dates)
01/01/12
02/01/12
Table 2 (counts)
01/01/12 | Item 1 | 10
01/01/12 | Item 2 | 15
03/01/12 | Item 1 | 5
I have to join the two tables, not leaving gaps in dates:
An OUTER JOIN did the trick.
I want to have the last available number if that date is missing in Table 2.
E.g.
02/01/12 | Item 1 | 10
02/01/12 | Item 2 | 15
I am struggling on this. Any hints?

A query can transform, and join data, but it cannot generate new data (rows) that were not there to begin with. In your case if the 02/01/12 data row is missing you aren't going to be able to create rows on the fly to fill in the gaps in your query results.
To fix, create a 3rd table or sub-query that contains all of the lookup date segments that you need in your results, and include that in your outer join on the outer query.

Okay, so we have [Table1]
Date
----------
2013-01-01
2013-02-01
2013-03-01
and [Table2]
Date Item Qty
---------- ------ ---
2013-01-01 Item 1 10
2013-01-01 Item 2 15
2013-03-01 Item 1 5
We can start by creating a saved query in Access named [DesiredRows] to give us the complete set of Date/Item values we want to see:
SELECT Table1.Date, i.Item
FROM
Table1,
(SELECT DISTINCT Item FROM Table2) AS i
...returning
Date Item
---------- ------
2013-01-01 Item 1
2013-02-01 Item 1
2013-03-01 Item 1
2013-01-01 Item 2
2013-02-01 Item 2
2013-03-01 Item 2
Now we can use that query as part of a saved query named [LastAvailableDates] to give us the last available date in Table2 for each of those pairs
SELECT
DesiredRows.Date,
DesiredRows.Item,
MAX(Table2.Date) AS LastAvailableDate
FROM
DesiredRows
INNER JOIN
Table2
ON Table2.Item = DesiredRows.Item
AND Table2.Date <= DesiredRows.Date
GROUP BY DesiredRows.Date, DesiredRows.Item
...returning
Date Item LastAvailableDate
---------- ------ -----------------
2013-01-01 Item 1 2013-01-01
2013-01-01 Item 2 2013-01-01
2013-02-01 Item 1 2013-01-01
2013-02-01 Item 2 2013-01-01
2013-03-01 Item 1 2013-03-01
2013-03-01 Item 2 2013-01-01
Finally, we can use that query in a query to retrieve the final results
SELECT
LastAvailableDates.Date,
LastAvailableDates.Item,
Table2.Qty
FROM
LastAvailableDates
INNER JOIN
Table2
ON Table2.Date = LastAvailableDates.LastAvailableDate
AND Table2.Item = LastAvailableDates.Item
...returning
Date Item Qty
---------- ------ ---
2013-01-01 Item 1 10
2013-01-01 Item 2 15
2013-02-01 Item 1 10
2013-02-01 Item 2 15
2013-03-01 Item 1 5
2013-03-01 Item 2 15

Related

SQL - Some result when no row

I have a table (DATA), from which I would like to perform some simple math queries
Security Date Price
-------- ---- ------
1 2017-08-31 130
2 2017-08-31 150
1 2017-07-31 115
2 2017-07-31 140
1 2017-06-30 100
2 2017-06-30 130
1 2017-05-31 90
1 2017-04-30 85
1 2017-03-31 80
SELECT x.Security, x.Price/y.Price-1 'MONTHLY RETURN', x.Price/z.Price-1 'QUARTERLY RETURN'
FROM DATA AS x
JOIN DATA AS y
ON x.Security = y.Security
JOIN DATA AS z
ON x.Security = z.Security
WHERE x.Security IN (1,2)
AND x.Date = '2017-08-31'
AND y.Date = '2017-07-31'
AND z.Date = '2017-05-31'
I would like to have full table, even when there is no result (150/NO ROW)-1
Security MONTHLY RETURN QUARTERLY RETURN
-------- -------------- ----------------
1 (130/115)-1 (130/90)-1
2 (150/140)-1 NULL or any other data
Instead SQL is returning results just for Security 1 as there is no data (NO ROW) for Security 2 for '2017-05-31'. However it is not a good solution as I have data for '2017-07-31' so I would like to see them for Security 2.
Result of my query:
Security MONTHLY RETURN QUARTERLY RETURN
-------- -------------- ----------------
1 (130/150)-1 (130/90)-1
Is there any way to somehow prepare a table in which I will have all the data and let's say NULL when there is no result. Please note that normally I will have 20 or 30 securities.
I will be grateful for your assist on this one.
This is my second month with SQL and it is a way better than at the beginning but I still have some issues with logic. Do you know any good literature to start with?

TSQL query to return most recent record based on another columns value

I have a table that contains a list of expiration dates for various companies. The table looks like the following:
ID CompanyID Expiration
--- ---------- ----------
1 1 2016-01-01
2 1 2015-01-01
3 2 2016-04-02
4 2 2015-04-02
5 3 2014-01-03
6 4 2015-04-09
7 5 2015-07-20
8 5 2016-05-01
I am trying to build a TSQL query that will return just the most recent record for every company (i.e. CompanyID). Such as:
ID CompanyID Expiration
--- ---------- ----------
1 1 2016-01-01
3 2 2016-04-02
5 3 2014-01-03
6 4 2015-04-09
8 5 2016-05-01
It looks like there is a exact correlation between ID and Expiration. If that is true, ie the later the Expiration the higher the ID, then you could simply pull Max(ID) and Max(Expiration) which are 1:1 and group by CompanyID:
Select max(ID), CompanyID, max(Expiration) from Table group by Company ID

sql Query on effective date

I would like to get report for drink purchased in whole month but price of the drink can change any time in month and I would like to get report for a month with price change
I have two tables
SELECT [ID]
,[DrinkID]
,[UserID]
,[qty]
,[DateTaken]
FROM [Snacks].[dbo].[DrinkHistory]
SELECT [ID]
,[DrinkID]
,[UserID]
,[qty]
,[DateTaken]
FROM [Snacks].[dbo].[DrinkHistory]
[DrinkHistory]:
ID DrinkID UserID qty DateTaken
----------------------------------------------------------------------
1 1 1 1 2014-05-10
2 1 1 2 2014-05-15
3 2 1 1 2014-06-01
4 2 1 4 2014-06-01
5 1 1 3 2014-05-20
6 1 1 4 2014-05-30
[DrinkPricesEffect]:
PriceID DrinkID DrinkPrice PriceEffectiveDate IsCurrent
-----------------------------------------------------------------------------------
1 1 10.00 2014-05-01 1
2 1 20.00 2014-05-20 1
3 2 9.00 2014-06-01 1
4 2 8.00 2014-01-01 1
5 1 30.00 2014-05-25 1
6 1 40.00 2014-05-28 1
I would like to have result as under date taken between 2014-05-1 to 2014-05-31
DrinkId Qty Price DateTaken PriceEffectiveDate
-----------------------------------------------------------------------
1 1 10 2014-05-10 2014-05-01
1 2 10 2014-05-15 2014-05-01
1 3 20 2014-05-20 2014-05-20
1 4 40 2014-05-30 2014-05-28
Is there any who can give me some idea or write query for me?
If your drink price can change any time in a month you could additionaly save the price for each purchase. I would add a column [PricePaid] to the table [DrinkHistory].
When adding a record to [DrinkHistory], the price for the drink at the moment is known, but later it might change so you save the current price to the history...
Then for your result you could just display the Whole [DrinkHistory]
SELECT * FROM DrinkHistory;
This should work:
Select
DH.DrinkId,
DH.Qty,
DPE.DrinkPrice AS Price,
DH.DateTaken,
DPE.PriceEffectiveDate
FROM DrinkHistory DH
JOIN DrinkPricesEffect DPE ON DPE.PriceID =
(
Select Top 1 PriceID FROM
(
Select PriceID,RANK() OVER(ORDER BY PriceEffectiveDate DESC ) AS rnk
FROM DrinkPricesEffect
WHERE DH.DrinkId = DrinkId AND
DH.DateTaken >= PriceEffectiveDate
)SubQ WHERE rnk = 1
)
WHERE DH.DateTaken Between '2014-05-01' AND '2014-05-30'
Here you can find the SQL Fiddle link: http://sqlfiddle.com/#!6/5f8fb/26/0

How to find the first column in an ACCESS table row with a value not Zero of Blank?

I have a table which includes a column of each month (Jan-13, Feb-13, Mar-13, etc) for a period of four years. I need to find the first column in each row that has a value other than "0" (zero). Then I will need to find the last column with a value other than zero.
The query will let me know the start month and the end month of a resource. I have written an Excel formula but now I need to convert the same functionality to Access. When I find each of the columns I need to retrieve the column heading. Could anyone help me with the SQL for my query?
The report based on the query would be
ResourceName, StartDate EndDate
Bob Sample Apr-13 Apr-15
There are actual two tables involved. The Resource table with all the information for the individuals and a forecast table which has the months as columns and the resource id and task for rows. For each month an individual is forecast to work a given percent of their time. We are not concerned about the actual dates (11/20/201) the individual starts, just the month. So a resource for task 1 is forecast to work .5 percent of their time in Nov-13, which would be the first month that the resource work. Then that resource may be forecast to work at the same level for the next nine months. So the column for Aug-14 would be the last month with the .5 value. After that all columns contains zeros.
(I will limit my example to six months because I'm lazy.)
So we have some "wide" data in a table named [Forecast]:
ResourceID Jul-13 Aug-13 Sep-13 Oct-13 Nov-13 Dec-13
---------- ------ ------ ------ ------ ------ ------
1 0 0.5 1 0.5 0 0
2 0 0 2 0 0 0
3 0 0 3 4 0 0
Start by creating a saved query in Access named [ForecastUnpivoted] to convert the "short wide" data into "long skinny" data:
SELECT ResourceID, "2013-07" AS forecastMonth, [Jul-13] AS forecastValue
FROM Forecast
UNION ALL
SELECT ResourceID, "2013-08" AS forecastMonth, [Aug-13] AS forecastValue
FROM Forecast
UNION ALL
SELECT ResourceID, "2013-09" AS forecastMonth, [Sep-13] AS forecastValue
FROM Forecast
UNION ALL
SELECT ResourceID, "2013-10" AS forecastMonth, [Oct-13] AS forecastValue
FROM Forecast
UNION ALL
SELECT ResourceID, "2013-11" AS forecastMonth, [Nov-13] AS forecastValue
FROM Forecast
UNION ALL
SELECT ResourceID, "2013-12" AS forecastMonth, [Dec-13] AS forecastValue
FROM Forecast
which returns
ResourceID forecastMonth forecastValue
---------- ------------- -------------
1 2013-07 0
2 2013-07 0
3 2013-07 0
1 2013-08 0.5
2 2013-08 0
3 2013-08 0
1 2013-09 1
2 2013-09 2
3 2013-09 3
1 2013-10 0.5
2 2013-10 0
3 2013-10 4
1 2013-11 0
2 2013-11 0
3 2013-11 0
1 2013-12 0
2 2013-12 0
3 2013-12 0
Now we can use Min() and Max() to give us the start end end dates for each resource
SELECT
ResourceID,
Min(forecastMonth) AS StartMonth,
Max(forecastMonth) AS EndMonth
FROM ForecastUnpivoted
WHERE forecastValue <> 0
GROUP BY ResourceID
That gives us
ResourceID StartMonth EndMonth
---------- ---------- --------
1 2013-08 2013-10
2 2013-09 2013-09
3 2013-09 2013-10
In a relational database, you would not store your data like this. Instead, you would have 2 tables:
Your resources
The months in which a resource does work (for a task)
Example:
Table 1 resources:
ID | Resource_Name
1 | Mr. A
2 | Mrs. B
Table 2 Forecast:
FC_ID | FC_Month | FC_Resource_ID | FC_Task | FC_Percentage
1 | 2013-10-01 | 1 | actiontask! | 0.05
2 | 2013-11-01 | 1 | actiontask! | 0.10
3 | 2013-12-01 | 1 | actiontask! | 0.05
4 | 2013-07-01 | 2 | boring task | 0.3
5 | 2013-08-01 | 2 | boring task | 0.25
6 | 2013-09-01 | 2 | boring task | 0.3
7 | 2013-10-01 | 2 | boring task | 0.1
You can then request the start and end date using SQL:
SELECT Resource_Name, Min(FC_Month) AS colMin, Max(FC_Month) As colMax
FROM tblForecast INNER JOIN tblResources ON FC_Resource_ID=Resource_ID
GROUP BY FC_Resource_ID, Resource_Name
The result of this example will be:
Mr. A | 2013-10-01 | 2013-12-01
Mrs. B | 2013-07-01 | 2013-10-01

Find two consecutive rows

I'm trying to write a query that will pull back the two most recent rows from the Bill table where the Estimated flag is true. The catch is that these need to be consecutive bills.
To put it shortly, I need to enter a row in another table if a Bill has been estimated for the last two bill cycles.
I'd like to do this without a cursor, if possible, since I am working with a sizable amount of data and this has to run fairly often.
Edit
There is an AUTOINCREMENT(1,1) column on the table. Without giving away too much of the table structure, the table is essentially of the structure:
CREATE TABLE Bills (
BillId INT AUTOINCREMENT(1,1,) PRIMARY KEY,
Estimated BIT NOT NULL,
InvoiceDate DATETIME NOT NULL
)
So you might have a set of results like:
BillId AccountId Estimated InvoiceDate
-------------------- -------------------- --------- -----------------------
1111196 1234567 1 2008-09-03 00:00:00.000
1111195 1234567 0 2008-08-06 00:00:00.000
1111194 1234567 0 2008-07-03 00:00:00.000
1111193 1234567 0 2008-06-04 00:00:00.000
1111192 1234567 1 2008-05-05 00:00:00.000
1111191 1234567 0 2008-04-04 00:00:00.000
1111190 1234567 1 2008-03-05 00:00:00.000
1111189 1234567 0 2008-02-05 00:00:00.000
1111188 1234567 1 2008-01-07 00:00:00.000
1111187 1234567 1 2007-12-04 00:00:00.000
1111186 1234567 0 2007-11-01 00:00:00.000
1111185 1234567 0 2007-10-01 00:00:00.000
1111184 1234567 1 2007-08-30 00:00:00.000
1111183 1234567 0 2007-08-01 00:00:00.000
1111182 1234567 1 2007-07-02 00:00:00.000
1111181 1234567 0 2007-06-01 00:00:00.000
1111180 1234567 1 2007-05-02 00:00:00.000
1111179 1234567 0 2007-03-30 00:00:00.000
1111178 1234567 1 2007-03-02 00:00:00.000
1111177 1234567 0 2007-02-01 00:00:00.000
1111176 1234567 1 2007-01-03 00:00:00.000
1111175 1234567 0 2006-11-29 00:00:00.000
In this case, only records 1111188 and 1111187 would be consecutive.
Assuming the rows have sequential IDs, something like this may be what you're looking for:
select top 1 *
from
Bills b1
inner join Bills b2 on b1.id = b2.id - 1
where
b1.IsEstimate = 1 and b2.IsEstimate = 1
order by
b1.BillDate desc
select top 2 *
from bills
where estimated = 1
order by billdate desc
You should be able to do a descensing sorted query on estimated = true and select top 2. I am not the best at SQL so i cant give exact language structure
Do you have a column for "statement number", e.g., if Q12008 was statement 28 for a particular customer, then Q22008's bill would be 29, Q32008's bill would be 30 (assuming quarterly billing). You could then check that the statement numbers were adjacent rather than having to do date manipulation.