sql query to find missing records - sql

I am using a transaction table called Student_Details which contain Batch_No, PF_No, Emp_name,DOB, DOR and DOJ along with other details. There is another master table called Batch_Master which contains Batch_No, From_date, To_date and Due_date.
I want to get the details of staff whose due date is within Enter_date1 and Enter_date2 who actually fall due within this period and such of those staff whose due_date is earlier to Enter_date1 but still not come (i.e there is no record for the same person with a DOJ after due_date.)
Please help in designing a query in MS-Access

You should look specifically at SQL WHERE clause. I think this would be most beneficial for what you are trying to achieve. WHERE is used in these types of conditional statements to say if this is true (or false depending on the situation) then return this.
For example:
SELECT *
FROM <location>
WHERE Due_date > Enter_date1 AND Due_date < Enter_date2.
However I am really confused on this statement:
"such of those staff whose due_date is earlier to Enter_date1 but still not come (i.e there is no record for the same person with a DOJ after due_date"
To me this sounds like you just want to return every less than Enter_date2, but you want to ensure that there is only Unique records return... or so I assume.

Related

Oracle SQL - future date/employers age problem

I've got a problem with age of employeers.
In one table I have e_date_of_birth, e_employee_number, e_employee_name, and
in a second table w_employee_since.
I have an inquiry that returns employees with valid contracts for a particular day (e.g. 2016/01/01) and shows the current age of the employee on that day.
I need to add an inquiry that shows employees with valid contracts as of a specific date (e.g. 2016/01/01), and also their age of another date (e.g. 2017/01/01) in the same query results.
Without more details about your tables, particularly wherever you have the contracts information, a generic query to find employee age on a given date would look something like this.
SELECT FLOOR(MONTHS_BETWEEN(DATE '2017-01-01', e_date_of_birth)/12) AS age
FROM DUAL;

Sql query to delete duplicate rows

I have three tables.
Diagnose, Patient and PatientDiagnose
The tables look like this
Diagnose:
uuid,text,date
Patient:
uuid,name
PatientDiagnose:
patientuuid,diagnoseuuid
One patient can of course have multiple diagnoses and two patients can of course have the same diagnose but the two diagnoses are represented uniqly in Diagnose with different uuids. Therefore the two patients are represented in PatientDiagnose with their patient uuids and each one with those unique diagnose uuid.
Now I have found out that I would like to fix something in my DB. I would like to delete the diagnoses that are considered duplicates for a patient. Duplicates are: if they belong to the same patient and has the same text, within the same year (use of year function on date?) and leaving just one of those diagnoses intact.
I would like to remove those duplicates since I only want one diagnose pr patient of the same text, a year.
How can I do that in SQL?
Tommy
You say that a diagnose shall refer to exactly one patient. Your database, however, doesn't guarantee this, so you should fix that issue first. That would leave you with only two tables:
Patient: patientuuid, name
Diagnose: diagnoseuuid, text, date, patientuuid
Once you've converted your tables thus, you can easily do the cleanup:
delete from diagnose
where exists
(
select *
from diagnose other
where other.diagnoseuuid < diagnose.diagnoseuuid
and other.text = diagnose.text
and year(other.date) = year(diagnose.date)
and other.patientuuid = diagnose.patientuuid
);
You haven't mentioned which DBMS you are using. It may not feature the YEAR function. In that case try EXTRACT(YEAR FROM date) or look up date functions in your manual.

table design for time-dependent data

I would like to store some time-dependent data on MS SQL Server, for example employee salary history. Attributes include employee number, effective from date, salary, reason of change.
My question is "Should I include the effective to date on the table? " What is the best practice on storing this type of time-dependent data (current effective to = next effective from - 1), i.e. Should I include the value which can be deduce from another record ?
If effective to is to be stored, can I use Trigger to maintain its value?
Michael
What you seem to have is a slowly changing dimension. The best approach is based on how the data wil be used. After all, if you are never going to query the data, I can save you a bunch of time and perhaps money by advising you not to use a database at all.
That said, I would encourage you to have two dates on each row:
EffDate
EndDate
You can then determine the values of any of the values at any given point in history. This makes querying the data easier. But, when loading the table, you need to remember to update the EndDate of the previously active data. That is one extra step on the load.
If you only have EffDate, then the querying is more difficult, although the load is slightly easier. If the only thing you will ever do is choose an employee and look at the records in order, this might be sufficient.
As for the nature of the dates. If the dates are "continuous" (meaning they have a time component), then EndDate for one record should be equal to the EffDate of the next. Querying for a time would use:
where MYDATE >= EffDate and MYDATE < EndDate
If the dates are discrete, then I have the condition that the EndDate is one less than the next EffDate:
where MYDATE >= EffDate and MyDate <= EndDate
You could also use between for this condition (but be careful when using between on anything that looks like a date).
You need to have a child table with history of salaries, its primary key is a combined key (employeeId and a sequence id). This table will be your reference for data history.
ex:
empX, 1, fromDate 10/10/2012, toDate 11/10/2012, 1,980,000$,
empX, 2, .....
empX, 3,....
Your employee table will have the current salary and its effective date. this table will be faster to query from.
..and this employee is a lucky one ;)

Limiting results in a SQL query based on distinctness in an arbitrary column

I need to write a SQL query that pulls from a table that stores records for each time one of our salespeople speaks to a client. The relevant columns are: (1) the salesperson's employee ID, (2) the client's account number, and (2) the date of the conversation.
It's often the case that salespeople have spoken to clients multiple times within the report period (a calendar month) so there will be several entries that are nearly identical except for the date.
Where I'm getting tripped up is that, for the purpose of this query, I need to return only one record per salesperson/client combination, but I can't use DISTINCT because I need to include the date of the most recent conversation within the reporting period.
So, if salesperson John has spoken to client ABC on 10/10, 10/18, and 10/25 I need to pull the 10/25 record but not the others.
It's a Sybase database.
I have the feeling that I may be missing something simple here but I've tried searching and remain stumped. Any help is greatly appreciated.
Thanks for your time,
John
Guessing at the column names...
SELECT employee_id, client_acct_no,
MAX(conversation_date) AS MOST_RECENT_CONV_DATE
FROM mytable
WHERE conversation_date BETWEEN DATE '2010-10-01' AND DATE '2010-10-31'
GROUP BY employee_id, client_acct_no
Documentation for GROUP BY clause.

What is a fast way of joining two tables and using the first table column to "filter" the second table?

I am trying to develop a SQL Server 2005 query but I'm being unsuccessful at the moment. I trying every different approach that I know, like derived tables, sub-queries, CTE's, etc, but I couldn't solve the problem. I won't post the queries I tried here because they involve many other columns and tables, but I will try to explain the problem with a simpler example:
There are two tables: PARTS_SOLD and PARTS_PURCHASED. The first contains products that were sold to customers, and the second contains products that were purchased from suppliers. Both tables contains a foreign key associated with the movement itself, that contains the dates, etc.
Here is the simplified schema:
Table PARTS_SOLD:
part_id
date
other columns
Table PARTS_PURCHASED
part_id
date
other columns
What I need is to join every row in PARTS_SOLD with a unique row from PARTS_PURCHASED, chose by part_id and the maximum "date", where the "date" is equal of before the "date" column from PARTS_PURCHASED. In other words, I need to collect some information from the last purchase event for the item for every event of selling this item.
The problem itself is that I didn't find a way of joining the PARTS_PURCHASED table with PARTS_SOLD table using the column "date" from PARTS_SOLD to limit the MAX(date) of the PARTS_PURCHASED table.
I could have done this with a cursor to solve the problem with the tools I know, but every table has millions of rows, and perhaps using cursors or sub-queries that evaluate a query for every row would make the process very slow.
You aren't going to like my answer. Your database is designed incorrectly which is why you can't get the data back out the way you want. Even using a cursor, you would not get good data from this. Assume that you purchased 5 of part 1 on May 31, 2010. Assume on June 1, you sold ten of part 1. Matching just on date, you would match all ten to the May 31 purchase even though that is clearly not correct, some parts might have been purchased on May 23 and some may have been purchased on July 19, 2008.
If you want to know which purchased part relates to which sold part, your database design should include the PartPurchasedID as part of the PartsSold record and this should be populated at the time of the purchase, not later for reporting when you have 1,000,000 records to sort through.
Perhaps the following would help:
SELECT S.*
FROM PARTS_SOLD S
INNER JOIN (SELECT PART_ID, MAX(DATE)
FROM PARTS_PURCHASED
GROUP BY PART_ID) D
ON (D.PART_ID = S.PART_ID)
WHERE D.DATE <= S.DATE
Share and enjoy.
I'll toss this out there, but it's likely to contain all kinds of mistakes... both because I'm not sure I understand your question and because my SQL is... weak at best. That being said, my thought would be to try something like:
SELECT * FROM PARTS_SOLD
INNER JOIN (SELECT part_id, max(date) AS max_date
FROM PARTS_PURCHASED
GROUP BY part_id) AS subtable
ON PARTS_SOLD.part_id = subtable.part_id
AND PARTS_SOLD.date < subtable.max_date