What's the best way to find if a SQL record ceased to exist in a subsequent time period - sql

How can I generate a list of items that existed in one time period, but don't exist in a following time period. For example, a list of items that existed in January 2019, but did not appear in February 2019. I posted an idea of the sample query below, but I don't know how to approach this.
select period, item
from table
where period = 'February 2019'
and item (exists) in period -1
and item (does not exist) in period
Sample Data would be as follows (if there were three records, for example)
Period Item
January 2019 Bob
January 2019 Steve
January 2019 Phil
February 2019 Steve
February 2019 Phil
Desired results would be as follows:
Period Item
January 2019 Steve
Thank you for the help.

Based on your sample query, you should be able to use aggregation:
select item
from table
where period in ('February 2019', 'January 2019')
group by item
having min(period) = max(period) and
min(period) = 'January 2019';

You can use MONTH(yourdate) to get the month number and use that to get the desired results.
DECLARE #Month INT
SET #Month=1
SELECT * FROM
(SELECT * FROM #table WHERE month_number=#Month)current_period
LEFT JOIN
(SELECT * FROM #table WHERE month_number=#Month+1)following_period
ON
current_period.item=following_period.item
WHERE
following_period.item IS NULL
The SELECT after LEFT JOIN can be modified to Period_ID>#Month to include all the following periods.

Related

After certain week of 2022 and continue with this new year

I would like to request some advice about how to set a Where Condition, but after a certain week
What I mean is:
I have dirty data before a specific week of 2022, so I made this:
DATEPART(WK, SA.FECHAE) >= 44
AND
YEAR(SA.FECHAE) >= 2022
But, We're on 2023, so, I need to add the new information of this new year year too into the query.
The query result shows me until 12-31-2022 and need it until today after the week 44 of 2022
...
WHERE (
DATEPART(WEEK, SA.FECHAE) >= 44
AND YEAR(SA.FECHAE) = 2022
)
OR (
YEAR(SA.FECHAE) >= 2023
)
In the OPs question they ask how to add an additional date range to their WHERE clause. The addition of this OR allows a second date range (in this case anything where the year is greater than or equal to 2023) to match the predicate and be returned, without impacting the original.
Plain English definition of the amended where clause:
Week 44 of 2022, or any week of any year from 2023 forward.

SQL- How to filter registers where date is prior to previous month beginning?

I have this query with a SELECT statement and I need to add to my WHERE clause the condition that the date must be prior to the previous month beginning.
SELECT columnA, columnB
FROM TableX
WHERE columnA=20
For example the current date belongs to October so I need to filter the registers where date belongs to September or October from this year.
Let's say we are in December 2022, I would need to filter the registers whose date belongs to November 2022 or December 2022.
I am using an Oracle database.
How can I do it?
It should be something among the lines of:
SELECT columnA, columnB
FROM TableX
WHERE columnA = 20
AND <your_date_column> BETWEEN TRUNC(ADD_MONTHS(SYSDATE,-1),'MM') AND TRUNC(LAST_DAY(SYSDATE),'MM');

SQL - check if an order date occurs after the second Saturday in July

I am querying against a table of 4 yrs of order transactions (pk = order number) and I'm looking to tag each record with particular date flags based on the order date - e.g., calendar year, calendar month, fiscal year, etc. There are date attributes that are specific to our business (e.g., not easily solved by a datepart function) that I'm having trouble with.
I was able to add "School Year" (for us that runs Aug 1 - July 31) using a case statement:
case
when datepart(month, oline.order_date_ready) between 8 and 12 then datepart(year, oline.order_date_ready)
else (datepart(year, oline.order_date_ready)-1)
end as school_yr
So for 1/19/2017, the above would return "2016", because to us the 2016 school year runs from Aug 1 2016 to July 31 2017.
But now I'm having trouble repeating the same kind of case statement for something called "Rollover Year". All of our order history tables are reset/"rolled over" on the 2nd Saturday in July every calendar year, so for example the most recent rollover date was Saturday July 9th 2016. Click to view - rollover year date ranges
My above case statement doesn't apply anymore because I can't just add "datepart(month, oline.order_date_ready) = 7" - I don't need the whole month of July, I just need all the orders occurring after the 2nd Saturday in that July. So in this example, I need everything occurring from Sat July 9 2016 to today to be flagged as rollover_date = 2016.
Is there a flexible way to do this without hard coding previous/future rollover dates into another table? That's the only way I can think to solve it currently, but I'm sure there must be a better way.
Thanks!
If you ask for the day-of-the-week of July 1st, then from there it's simple arithmetic, right? This query gives results matching your image:
SELECT y,
CONCAT(y, '-07-01')::timestamp +
CONCAT(6 - EXTRACT(DOW FROM CONCAT(y, '-07-01')::timestamp) + 7, ' days')::interval
FROM generate_series(2013, 2020) s(y)
ORDER BY y DESC
;
So given any date d from year y, if it comes before the 2nd Saturday of July, give it fiscal year y - 1. Otherwise give it fiscal year (school year?) y.

Summarising MONTH value

I have a simple statement that starts:
SELECT a.product, MONTH(a.saledate) AS Month, Count(*) AS Total
Which yields, for example,
Product Month Total
Bike 8 1000
Please can anyone advise if it's possible to add the month's name to this query and also, is it possible to get a monthly total to appear as well?
Thanks!
The query in your example counts all the rows in your table, then presents that count next to a randomly chosen row's product and sale date. That's -- almost certainly -- not what you want. MySQL is quirky that way. Other DBMSs reject your example query.
If you want to display a monthly summary of product sold, here's the basic query:
SELECT a.product,
LAST_DAY(a.saledate) AS month_ending,
COUNT(*) AS Total
FROM table a
GROUP BY a.product, LAST_DAY(a.saledate)
The LAST_DAY() function is a great way to extract month and year from a date.
Finally, if you want to display the text name of the month, you can use the DATE_FORMAT() function to do that. %b as a format specifier gives a three-letter month name, and %M gives the full month name. So this query will do it.
SELECT a.product,
LAST_DAY(a.saledate) AS month_ending,
DATE_FORMAT(LAST_DAY(a.saledate), '%M %Y')) AS month
COUNT(*) AS Total
FROM table a
GROUP BY a.product, LAST_DAY(a.saledate)
In SQL Server 2012+ you can use the EOMONTH() function in place of LAST_DAY().
In SQL Server 2008+ you can use DATENAME(mm, a.saledate) to retrieve the month name from a date.
There are two ways of getting month name
1)
SUBSTRING('JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC ', (MONTH(a.saledate) * 4) - 3, 3)
2)
DATENAME(month, a.saledate)
Some poeple say You might be using MYSQL:
Then getting month name will be:
SELECT MONTHNAME( a.saledate);

MS Access grouping query spanning start and end dates

I would like to get a running tally of how many widgets were/are rented at any one time, by month, by year. Data is held in an MS Access 2003 db;
Table name: rent_table
Fields:
rentid
startdate
enddate
rentfee
rentcost
bookingfee
Something like; Count number of rentid's that fall between month/year, then group them?
e.g. if a widget was rented from 5th Jan 2014 to 8th April 2014 it would appear as a count in Jan, Feb, Mar and April tally's.
Many thanks.
EDIT
More details (sorry);
Access db is fronted by classic ASP.
If possible I don't want to create any new tables.
No input is required in order to run the report.
There are around 350-400 widgets that could be rented at any one time.
Each widget is rented exclusively.
Report output example;
Month | Year | NumRented
Jan 2014 86
Feb 2014 113
...
Can a query pick up dates within dates? So literally do a count of the table where date >Dec 31st 2013 AND <1st Feb 2014 (to grab a count for all of January 2014) and would that include the example of the rent starting on the 5th Jan? So I could just do twelve counts for each year?
create a calendar table, e.g.
table = cal_yyyymm with one column dt_yyyymm as numeric field
populate the table with ... say 5 or 10 years of data
201401 201402 201403 ... 60 or 120 rows, a small table
make a sql
Select
dt_yyyymm,
count(*) as cnt
From cal_yyyymm
Left Join rent_table
On format(startdate,"yyyymm") >= dt_yyyymm
And dt_yyyymm >= format(enddate,"yyyymm")
think about the complications in the data -- --
widget was rented from 5th Jan 2014 to 8th Jan 2014
and again rented from 11th Jan 2014 to 21st Jan 2014
does this count at 1 or 2 in the month?
if it is 1, then the sql gets more complicated because
the rent_table first needs to have its dates converted
to yyyymm format, and second needs to be de-duped on rentid,
and third then joined to cal_ On the dates...