Show all records for the same ID - database

I'm working on a Access project and I need help with something..
I have 2 tables, first one named tblHoliday, with fields (ID, OfficerID, OffType, From, To) [From] and [To] are Date Fields.
The second table is tblService with fields (ID, OfficerID, Date).
There is a relationship between [OfficerID] in each table.
Every [OfficerID] may have two records or more in a table tblService,,
I designed a form for tblHoliday to enter the officer's holiday, my question is (I need to check if any [Date] for the same [OfficerID] in the table tblService between [From] and [To], for OfficerID in the table tblHoliday), example: an officer ask for a holiday from 1/1/2017 to 1/10/2017 if he has a service in 1/3/2017 will give a message "the officer has a service on 1/3/2017"
My code works, but only for the first record in tblService for the same OfficerID
Dim dtmMyDate As Date
dtmMyDate = DLookup("Date", "tblService", "OfficerID = " & Me.OfficerID)
If dtmMyDate > Me.From And dtmMyDate < Me.To Then
MsgBox "The Officer has a Service"
Else
MsgBox "Done"
End If

Create a query:
Select
tblService.*
tblHoliday.*
Where
tblService.OfficerID = tblHoliday.OfficerID
And
tblService.Date Between tblHoliday.From And tblHoliday.To
Open a recordset from this or assign it to a listbox to either loop or list the offending service days.

Related

MSSQL, how compare records with dataframe table?

let's say we have a table with invoices and employees ID
and another table for vacation which also contains an employee ID.
In this case only emplyee1 had vacation a these date frames.
Now we have to compare if the invoice date is between or exactly at the date frames of vacation table.
The aim is: The invoice date has to be compared, if an employee is on vacation the calc_flag = 0, if not then always=1. E.g. employee1 was from 2023/01/05 till 2023/01/12 on vacation.
So all his invoices must be calc_flag=0 for this time.
How to create the sql query in mssql for this topic?
Thanks for any advice.
I already tried to check the dateframes but if there are several entries in vacation table, I'm not sure how to handle it.
One way to do this is a LEFT JOIN to check for existance. Perhaps you need to tweak the < or > depening if you would like to include the Begin and or End date.
SELECT i.InvNo,
i.emp_ID,
i.InvDate,
i.calc_flag ,
CASE WHEN v.Emp_ID IS NOT NULL THEN 0 ELSE 1 END AS calc_flage
FROM dbo.invoices AS i
LEFT JOIN dbo.vacation AS v ON v.Emp_ID = i.emp_ID AND v.[Begin] < i.InvDate AND v.[End] > i.InvDate

How to determine id date falls under one of the ranges (ranges are stored in separate rows of another table)

I have SalesFacts Table, which contains Sales_Amount, Customer_ID and Invoice_Date.
In another table I have Information's about special agreements for some of the customers (columns are: Customer_ID, Agreement_Start_Date, Agreement_End_Date).
Now - i would like to check, if the sales from SalesFact table occurred when special agreement was active for the Customer. This would be pretty easy, if there was only one date range when special agreement was active. However, in my case, Table with Special Agreements date ranges contains duplicated Customer ID, because for one Customer there might be several time ranges, where special agreement was active.
E.G. In SalesFact Table I have 3 transactions for one customer:
In SpacialAgreements Table I can see, that there are 2 data ranges when this customer had a right to special agreements.
I would like to create a query, that adds additional column to my SalesFacts table, that would determine, if the transaction happened when there was a Special Agreement Active. So in case shown above, it would be:
If there was Only one date range with special agreement it would be pretty easy:
Select
S.[Sales_Amount], S.[Customer_ID], S.[Invoice_Date],
IIF(S.[Invoice_Date] >= A.[Agreement_Start_Date] and S.[Invoice_Date]<=A.[Agreement_End_Date],'YES','NO') as AGREEMENT
From SalesFacts S left join SpacialAgreements A on S.[Customer_ID] = A.[Customer_ID]
But since there are several date ranges in SpacialAgreement table, i don't know how to achieve that properly, without risking any duplicates in Sales_Amount and without loosing any data.
Any ideas?
If you want to get data exactly as you shown in question then for the SELECT statement you can use something like this:
SELECT
S.[Sales_Amount],
S.[Customer_ID],
S.[Invoice_Date],
CASE WHEN EXISTS (SELECT 1
FROM SpacialAgreements A
WHERE A.Customer_ID = S.Customer_ID
AND S.[Invoice_Date] >= A.[Agreement_Start_Date]
AND S.[Invoice_Date] <= A.[Agreement_End_Date])
THEN 'YES'
ELSE 'NO'
END as Agreement
FROM SalesFacts S
So, this solution can be used if you are selecting data or creating view from this query.
If you want to have persisted value as one physical column in your SalesFacts table then you can try to solve your problem with triggers.

Design of Table when it comes to multiple dates for selection

I have a table Hall which has structure like
CREATE TABLE Hall_tbl (
hall_id INTeger PRIMARY KEY AUTOINCREMENT NOT NULL,
name TEXT,
price INTEGER,
capacity INTEGER,
availibility INTEGER
);
Now, intention of the application is to make it work in a way that User looks at the calendar -> Selects a date -> If Hall is available on that particular day then User can interact with it else not.
So, it boils down to the point that Availibility is important and it should be reference to bunch of Dates. Once user open a particular date, he is presented with Time Slots. Depending on the Available Time Slots user can select the Hall. I am having hard time in getting idea how would it be possible to implement that.
First I thought to create a table called dates with columns date starting from 1-1-2018 to 1-1-2020 and create multiple time slot like 0-1 1-2 .. 2-24 and putting 0 to indicate they are not sold and I will change to 1 when User select an open Hall. But this will take me to create 365*4 rows and 25 columns which is not at all efficient. So how can I do this ?
Many application related to Ticket Booking, Flight booking have already implemented such stuff. So, How do they do it efficiently ??
Technology I am using is SQLITE
What you could do is have a table for the opening dates and add just the opening dates and then check if there is a row for the date if so then the hall is open otherwise it is not.
So based upon your Hall_tbl your could have :-
Your Hall_tbl
CREATE TABLE IF NOT EXISTS Hall_tbl (
hall_id INTEGER PRIMARY KEY,
name TEXT,
price INTEGER,
capacity INTEGER,
availibility INTEGER
);
AUTOINCREMENT isn't required and it is recommended to not use it unless necessary SQLite Autoincrement
availability column isn't required but has been left
Add some halls (4 id's 1-4)
INSERT INTO Hall_tbl (name, price, capacity, availibility)
VALUES('Grand Hall',200,50,0),
('Large Hall',100,25,0),
('Normal Hall',75,20,0),
('Small Hall',50,15,0);
The Hall opening times table
CREATE TABLE IF NOT EXISTS hall_opening_times (hall_reference, open_date);
Add some opening times (5)
INSERT INTO hall_opening_times
VALUES (1,'2018-04-23'), -- Grand hall open on 2018-04-23
(2,'2018-04-23'), -- Large Hall open on 2018-04-23
(2,'2018-04-25'), -- Large Hall open on 2018-04-25
(3,'2018-04-24'), -- Normal Hall open on 2018-04-24
(4,'2018-04-23'); -- Small Hall open on 2018-04-23
Checking if a hall is open
The following would return a single row with a single column where the value would be 0 (not open) or 1 (open) :-
This checks the Grand Hall for today (it's 2018-04-23 here)
SELECT count() > 0 AS hall_open FROM hall_opening_times WHERE hall_reference = 1 AND date(open_date) = date('now');
it returns 1 (in column hall_open) as the Grand Hall (ID = 1) is open on 2018-04-03 today (date('now'))
This one checks the Normal Hall for today
SELECT count() > 0 AS hall_open FROM hall_opening_times WHERE hall_reference = 3 AND date(open_date) = date('now');
it returns 0 (in column hall_open) as there are no entries for ID 3 on 2018-04-03
A little more
You could get a list of Open Halls using the following :-
SELECT group_concat(name,' - ') AS open_halls
FROM hall_opening_times JOIN Hall_tbl ON hall_reference = Hall_tbl.hall_id
WHERE open_date = date('now')
Which on 2018-04-23 would return (in column open_halls):-
Grand Hall - Large Hall - Small Hall
If the previous SQL were change to (to check tomorrow 2018-04-24) :-
SELECT group_concat(name,' - ') AS open_halls
FROM hall_opening_times JOIN Hall_tbl ON hall_reference = Hall_tbl.hall_id
WHERE open_date = date('now','+1 DAY')
Then it would return :-
Normal Hall
You could prune past open_times (if wanted) using something like :-
DELETE FROM hall_opening_times WHERE open_date < date('now','-1 WEEK');
will delete rows older than 1 week from the current date.
Note regarding date formats
The date format yyyy-MM-dd is one recognised/supported by SQLite date functions using that rather than d-M-yyyy can make things significantly simpler.
See - SQL As Understood By SQLite - Date And Time Functions

Problèm with SQL select grouping

I have a small problem with a SQL Server query.
I have an issue with my view of several base tables with duplicate values, so far no problem, these duplicates are logical. By unfortunately I do not get the desired end result, I could do it by programming the front end of my application but I would prefer to do the work on the server.
I will explain the principle:
I have 30 companies which each have an employee table.
My view is a union of the 30 employee tables.
Each employee has a unique serial number, the number is the same across tables, so an employee named "John Doe" with an ID number 'S0000021' can be hired in Company A then transferred to company Q without any problems, it will retain the serial number 'S0000021'.
The difference between the data from the Employee tables A and Q will be in this example the start (hire) and release (transfer) dates entered for Company A and just the start date for company Q so the view will have 2 lines for "John Doe".
12 common fields are the following:
Serial Number (Identical in every employee table)
Social Security Number (Same in every employee table)
Start/Hire Date
Release/Transfer date (empty/null if the employee is current)
Name (Can change across companies if the person divorces)
First name
Maiden name
Last Name
Gender
Final Released
Company Code
The problem seems simple that I would not appear that the latest information of the employee, except with a group by, if it has changed name or release date, it will be displayed twice.
I tried the following different ways but they don't return what I want
I returned results both ways but I always see duplicates because my dates within companies are never identical, and their name may change.
Sorry for this Google translation.
1 --
select
vue.matricule,
vue.numsecu,
vue.name,
vue.lastname,
vue.maidenname,
vue.secondname,
vue.genre,
vue.released,
vue.companycode
from
vue
group by
vue.matricule,
vue.numsecu,
vue.name,
vue.lastname,
vue.maidenname,
vue.secondname,
vue.genre,
vue.released,
vue.companycode
2---
select
distinct(vue.matricule),
vue.numsecu,
vue.name,
vue.lastname,
vue.maidenname,
vue.secondname,
vue.genre,
vue.released,
vue.companycode
from
vue
I assumed the following:
there is a view (vue) that already gathers all data from each of the 30 companies
you are just looking for the latest record for each employee
If you need to also see a record for each name change we can change this.
--set up test data
declare #vue table (
matricule varchar(20),
numsecu varchar(20),
name varchar(20),
lastname varchar(20),
maidenname varchar(20),
secondname varchar(20),
genre varchar(20),
start datetime,
released datetime,
companycode varchar(20));
insert #vue values
('S0000021','123456789','John', 'Doe',null,null,'M','2015-01-01','2015-12-31','A'),
('S0000021','123456789','Johnny', 'Doe',null,null,'M','2016-01-01',null,'Q'), --new company, name change, currently employed
('S0000022','123456780','Jane', 'Doe',null,null,'M','2015-01-01','2015-12-31','A'),
('S0000022','123456780','Jane', 'Doe',null,null,'M','2016-01-01','2016-02-01','Q'); --new company, name change, terminated
select * from #vue order by matricule, start;
--get latest record for each employee
select *
from (--add row numbering
select *, row_number() over (partition by matricule order by start desc) row_num
from #vue
) vue2
where vue2.row_num = 1;

How can I create a table that combines the date for multiple users even if it's null date for that user?

I'm trying to create a table that shows the history of every users purchase history. I have one table that shows the date, #DateTable and another table that shows each individual purchase with columns, "UserNumber" and "PurchaseDate" and "Purchaseamount"
How can I join these two together to get the sum of each users Purchaseamount for every single day, even if they don't make a purchase that day?
Maybe you can accomplish this by using only your second table?
SELECT UserNumber,
PurchaseDate,
(CASE
WHEN PurchaseAmount IS NULL THEN '0'
ELSE SUM(PurchaseAmount)
END) PurchaseAmount
FROM PurchaseTable
GROUP BY UserNumber, DAY(PurchaseDate)
If the above doesn't work, try modifying to WHEN SUM(PurchaseAmount) IS NULL...

Resources