SQL Access -- Keep record only with most recent timestamp - sql

I have a table that appears as follows:
Time Name Cust_ID Num_Calls Num_Orders
12.00 ABC 100 20 10
12.25 PQR 102 23 12
12.30 ABC 100 26 15
01.00 ABC 100 26 18
02.00 PQR 102 23 14
04.00 PQR 102 25 20
How do I delete the earlier records for each "Name & Cust_ID" and keep the most recent one. The other fields in the record may change as I run them through my Access Database, but Name and ID remains the same.
My output at the End of the Day should be:
Time Name Cust_ID Num_Calls Num_Orders
01.00 ABC 100 26 18
04.00 PQR 102 25 20

I think if your cust_id is unique, you should make it a primary key in the table.
Then whenever you have a new entry, first check and see if the current cust_id already exists.
If yes, update that entry in the table.
Else do an insert.

Try this...
This should give you your most recent records based on max(time), you could delete the complement of this set.
SELECT * FROM YOUR_TABLE A
INNER JOIN
( SELECT MAX(time) MAX_time
, NAME , CUST_ID
FROM YOUR_TABLE
GROUP BY
NAME , CUST_ID )B
ON A.NAME=B.Name
and A.CUST_ID=B.CUst_ID
and A.time =B.max_time
So you would delete the following records
DELETE FROM YOUR_TABLE
WHERE EXISTS
(SELECT * FROM YOUR_TABLE B
WHERE TIME <>( SELECT MAX(time) FROM YOUR_TABLE C WHERE B.NAME=C.Name
and C.CUST_ID=B.CUst_ID )
AND A.NAME=B.Name
and A.CUST_ID=B.CUst_ID)

Related

Count values separately until certain amount of duplicates SQL

I need a Statement that selects all patients and the amount of their appointments and when there are 3 or more appointments that are taking place on the same date they should be counted as one appointment
That is what my Statement looks so far
SELECT PATSuchname, Count(DISTINCT AKTDATUM) AS AKTAnz
FROM tblAktivitaeten
LEFT OUTER JOIN tblPatienten ON (tblPatienten.PATID=tblAktivitaeten.PATID)
WHERE (AKTDeleted<>'J' OR AKTDeleted IS Null)
GROUP BY PATSuchname
ORDER BY AKTAnz DESC
The result should look like this
PATSuchname Appointments
----------------------------------------
Joey Patner 13
Billy Jean 15
Example Name 13
As you can see Joey Patner has 13 Appointments, in the real table though he has 15 appointments but three of them have the same Date and because of that they are only counted as 1
So how can i write a Statement that does exactly that?
(I am new to Stack Overflow, sorry if the format I use is wrong and tell me if it is.
In the table it looks like this.
tblPatienten
----------
PATSuchname PATID
------------------------
Joey Patner 1
Billy Jean 2
Example Name 3
tblAktivitaeten
----------
AKTDatum PATID AKTID
-----------------------------------------
08.02.2021 1 1000 ----
08.02.2021 1 1001 ---- So these 3 should counted as 1
08.02.2021 1 1002 ----
09.05.2021 1 1003
09.07.2021 2 1004 -- these 2 shouldn't be counted as 1
09.07.2021 2 1005 --
Two GROUP BY should do it:
SELECT
x.PATID, PATSuchname, SUM(ApptCount)
FROM (
SELECT
PATID, AKTDatum, CASE WHEN COUNT(*) < 3 THEN COUNT(*) ELSE 1 END AS ApptCount
FROM tblAktivitaeten
GROUP BY
PATID, AKTDatum
) AS x
LEFT JOIN tblPatienten ON tblPatienten.PATID = x.PATID
GROUP BY
x.PATID, PATSuchname

Delete duplicate rows in Access SQL-Query

i want to create an Access SQL Query for deleting duplicate rows.
My Table:
CustID EventDate EventID
12 01.01.2019 1001
10 02.01.2019 1002
11 03.01.2019 1003
10 01.01.2019 1001
11 03.01.2019 1004
The table has no primary key.
I want to delete every duplicate CustID.
The result should have every CustID once with
Prio 1. the most recent EventDate
Prio 2. the biggest EventID
The result would look like this:
CustID EventDate EventID
12 01.01.2019 1001
10 02.01.2019 1002
11 03.01.2019 1004
I don't want to use macros.
How would the sql statement look like in access?
Thank you in advance.
Assuming most recent date and biggest event ID will always be in the same record, consider:
Query1:
SELECT Table1.CustID, Max([EventDate] & [eventID]) AS ID
FROM Table1
GROUP BY Table1.CustID;
Query2:
DELETE FROM Table1 WHERE Not CustID & EventDate & EventID IN (SELECT CustID & ID
FROM Query1);
You can apply the conditions for deletion with EXISTS:
DELETE FROM tablename AS t
WHERE EXISTS (
SELECT 1 FROM tablename
WHERE
CustID = t.CustID
AND
(EventDate > t.EventDate OR (EventDate = t.EventDate AND EventID > t.EventID))
)
This will help you :
Select distinct * into ‪#‎tmpl‬ From MY_TABLE
Delete from MY_TABLE
Insert into MY_TABLE
Select * from #tmpl
Drop table #tmpl
While creating temp tables if throw errors, then create another real table and perform the same.

Calculate MonthlyVolume - PIVOT SQL

I am using SQL server 2008 and I have following Table with millions of rows...Here are few sample records
Serial_Num ReadingDate M_Counter Dyn_Counter
XYZ 3/15/2014 100 190
XYZ 4/18/2014 140 240
XYZ 5/18/2014 200 380
ABC 3/12/2014 45 40
ABC 4/19/2014 120 110
ABC 5/21/2014 130 155
This table will always have only one reading for each month and no missing months....
and I would like calculate M_Counter and Dyn_Counter values for each month, For an example XYZ -> May month calculated counter value should be 60 = 200 (05/18/2014 value) - 140 (04/18/2014 value). I would like to insert data into another table in following way.
CalculatedYear CalculatedMonth Serial_Num M_Counter_Calc Dyn_Counter_Calc
2014 4 XYZ 40 50
2014 5 XYZ 60 140
2014 4 ABC 75 70
2014 5 ABC 10 45
Any help really appreciated!
If you're using MS SQL, something like this should work. The concept is to sort the dataset based on Serial_Num and ReadingDate. Add a sequential Row ID and store into a temp table. Join the table onto itself such that you match up the current row with the previous row where the serial numbers still match. If there wasn't a prior month's reading, the value will be null. We use Isnull( x, 0) to account for this when doing the calculations.
declare #Temp1 table
(
RowID int,
Serial_Num varchar(3),
ReadingDate datetime,
M_Counter int,
Dyn_Counter int
)
insert into #Temp1
select ROW_NUMBER() over (order by Serial_Num, ReadingDate), *
from MyTable T
select
Year(T1.ReadingDate) As CalculatedYear,
Month(T1.ReadingDate) as CalculatedMonth,
T1.Serial_Num,
T1.M_Counter - ISNULL(T2.M_Counter,0) as Calculated_M_Counter,
T1.Dyn_Counter - isnull(T2.Dyn_Counter,0) as Calculated_Dyn_Counter
from #Temp1 T1
left outer join #Temp1 T2 on T1.RowID = T2.RowID + 1 and T1.Serial_Num = T2.Serial_Num
order by T1.Serial_Num, Year(T1.ReadingDate), Month(T1.ReadingDate)

How Do I Select All Parents and the Top Previous Child Record Based on Dates in SQL Server 2008

I'm using a vendor provided database running on SQL Server 2008. There are two tables that track tests. For every record in Table A there may be zero, one or multiple records in Table B. There can also be multiple tests in Table A for the same user. The relationship is TableA.UserID = TableB.UserID. Tests taken in Table B can occur before or after Table A.
I need to select all of the records in Table A and, if test(s) from Table B have been taken by the same user before the test in Table A, data from Table B but only from the last previous child record. Both tables are structured similarly:
**TABLE A**
TestID INTEGER PRIMARY KEY,
UserID INTEGER,
TestDate DATE,
Score INTEGER
TABLE B
TestID INTEGER PRIMARY KEY,
UserID INTEGER,
TestDate Date,
Score INTEGER
Sample Data
TABLE A
TestID UserID TestDate Score
1 100 2014-02-15 80
2 101 2014-02-20 100
3 102 2014-02-22 90
4 102 2014-03-10 70
TABLE B
TestID UserID TestDate Score
1000 100 2014-02-01 55
1007 100 2014-02-05 85
1012 100 2014-02-20 95
1034 102 2014-02-12 65
1205 102 2014-03-05 75
1986 101 2014-03-10 45
What I'd like returned would be:
UserID TestA_ID TestADate TestAScore TestB_ID TestBDate TestBScore
100 1 2014-02-15 80 1007 2014-02-05 85
101 2 2014-02-20 100 NULL NULL NULL
102 3 2014-02-22 90 1034 2014-02-12 65
102 4 2014-03-10 70 1205 2014-03-05 75
I've know how to get all of the previous Table B rows joined to the Table A rows by using a LEFT OUTER JOIN and filtering by date in the WHERE clause, and I know how to get the Top row from Table B, but I haven't been able to work out how to get the top child record that occurs before the date of the record in Table A. Any help would be appreciated. Thanks.
You can do this using OUTER APPLY in T-SQL.
For each record in TableA, we're looking for a record in TableB for the same user but with a test date prior to the test date in TableA and we're also ordering the test in TableB to ensure we're getting the most recent test from TableB (but still prior to the test date from TableA).
SELECT
A.[UserID],
A.[TestID] [TestA_ID],
A.[TestDate] [TestADate],
A.[Score] [TestAScore],
B.[TestB_ID],
B.[TestBDate],
B.[TestBScore]
FROM [TableA] A
OUTER APPLY
(
SELECT TOP 1
B1.[TestID] [TestB_ID],
B1.[TestDate] [TestBDate],
B1.[Score] [TestBScore]
FROM [TableB] B1
WHERE A.[UserID] = B1.[UserID]
AND A.[TestDate] > B1.[TestDate]
ORDER BY
B1.[TestDate] DESC
) B
Or another option might be to use the ROW_NUMBER() window function to find the record from TableB. I have a hunch this one wouldn't perform as well because it needs to hit TableA twice, but can't be sure without running tests.
SELECT
A.[UserID],
A.[TestID] [TestA_ID],
A.[TestDate] [TestADate],
A.[Score] [TestAScore],
B.[TestB_ID],
B.[TestBDate],
B.[TestBScore]
FROM [TableA] A
LEFT JOIN
(
SELECT
ROW_NUMBER() OVER (PARTITION BY A.[UserID], A.[TestID] ORDER BY B.[TestDate] DESC) [rn],
A.[UserID],
A.[TestID] [TestA_ID],
B.[TestID] [TestB_ID],
B.[TestDate] [TestBDate],
B.[Score] [TestBScore]
FROM [TableA] A
INNER JOIN [TableB] B
ON A.[UserID] = B.[UserID]
AND A.[TestDate] > B.[TestDate]
) B
ON A.[UserID] = B.[UserID]
AND A.[TestID] = B.[TestA_ID]
AND B.[rn] = 1

Split a Table into 2 or more Tables based on Column value

I have a Table called "MIVTable" which has the following records,
MIVID Quantity Value
------ ---------- --------
14 10 3000
14 20 3500
14 15 2000
15 20 3000
15 50 7500
16 25 2000
Here, I need to store the above Table into two tables such as "HeaderTbl" and "DetailTbl" based on the MIVID as follows:
HeaderTbl:
HID MIVID TotalQuantity TotalValue
----- ------- ------------- -----------
1 14 45 8500
2 15 70 10500
3 16 25 2000
Here HID is the Primary Key with Identity Column.
DetailTbl:
HID MIVID Quantity Value
----- ------- ------------ -------
1 14 10 3000
1 14 20 3500
1 14 15 2000
2 15 20 3000
2 15 50 7500
3 16 25 2000
Suppose, if the MIVTable contains 4 different MIVID means, then 4 row should be created based on the MIVID on the HeaderTbl. How to do this?
To insert records in HeaderTbl from MIVTable use this: (HID should be auto increment)
INSERT INTO HeaderTbl
([MIVID], [TotalQuantity], [TotalValue])
SELECT MIVID, SUM(Quantity), SUM(Value) FROM MIVTable GROUP BY MIVID;
To insert records in DetailTbl from HeaderTbl and MIVTable use this:
INSERT INTO DetailTbl
([HID], [MIVID], [Quantity], [Value])
SELECT H.HID, M.*
FROM HeaderTbl H
INNER JOIN MIVTable M
ON H.MIVID = M.MIVID;
Look at this SQLFiddle
Here you need to use INSERT INTO SELECT statement to insert data from one table to another. You can also use JOIN in such statement as I did it for DetailTbl.
You would generate the HeaderTbl using RANK() SQL Server function, as follows:
SELECT RANK() OVER (ORDER BY MIVID) as HID, MIVID, TotalQuantity, TotalValue
FROM
(
SELECT
MIVID,
SUM(Quantity) as TotalQuantity,
SUM(Value) as TotalValue
FROM MIVTable GROUP BY MIVID
) AS A
and the Detail table using the ROW_NUMBER() SQL Server function, as follows:
SELECT
ROW_NUMBER() OVER (ORDER BY MIVID) AS HID,
MIVID,
Quantity,
Value
FROM MIVTable