Oracle: Retrieving specific group of records based by date - oracle

I have a table in oracle that I'm trying to write a query for but having a problem writing it correctly. The data of the table looks like this:
Name
ID
DATE
Shane
1
01JAN2023
Angie
2
02JAN2023
Shane
1
02JAN2023
Austin
3
03JAN2023
Shane
1
03JAN2023
Angie
2
03JAN2023
Tony
4
05JAN2023
What I was trying to come up with was a way to iterate over each day, look at all the records for that day and compare with the rest of the records in the table that came before it and only pull back the first instance of the record based on the ID & Date. The expected output would be:
Name
ID
DATE
Shane
1
01JAN2023
Angie
2
02JAN2023
Austin
3
03JAN2023
Tony
4
05JAN2023
Can anyone tell me what the query should be to accomplish this?
Thank you in advance.

You'll need to convert your date field to a real date so it orders correctly
SELECT name,id,MIN(TO_DATE(date,'DDMONYYYY')) date
FROM table
GROUP BY name,id

Isn't that just
select name, id, min(date_column)
from your_table
group by name, id;

If you don't want to use aggregation, you can use FETCH NEXT ROWS WITH TIES:
SELECT tab.*
FROM tab
ORDER BY ROW_NUMBER() OVER(PARTITION BY Name, Id ORDER BY DATE_)
FETCH NEXT 1 ROWS WITH TIES
Output:
NAME
ID
DATE_
Angie
2
02-JAN-23
Austin
3
03-JAN-23
Shane
1
01-JAN-23
Tony
4
05-JAN-23
Check the demo here.

Related

How to query distinct column value when query all row data

I hava one MySQL Table
id name birthdate city
1 Owen 2011/01/01 USA
2 Mark 2012/05/01 UK
3 Marry 2011/01/01 JP
4 John 2011/01/01 JP
First,I uesd jqgrid to read all row data. But Now,I want to know when birthdate=2011/01/01,how many different city in the table.
Can don't used sql,only used jqgrid plugin?
You are looking for distinct function.
SELECT DISTINCT(city) FROM table WHERE birthday = "2011/01/01";

What if I want Oracle SQL to GROUP BY this but not that?

This is what I get previously from another SQL code:
Customer Id week_ending Purchase Id Price
1234 2/28/2015 8604220 15
1234 2/28/2015 8604220 13.75
1234 2/28/2015 8604220 12.95
1234 2/28/2015 8604220 18.95
567890 8/15/2015 6376243 5.15
567890 8/15/2015 6376243 0.89
567890 8/15/2015 6376243 3.99
567890 8/15/2015 6376243 2.3
1234 1/24/2015 8824241 0.99
1234 1/24/2015 8824241 3.99
1234 1/24/2015 8824241 3.89
Now I want to sum the price by Purchase ID since it is unique for every of our customer's order but I don't want my SQL to think and sum it by Customer ID (since each customer could order multiple times with multiple Purchase ID). Following is my code that I wrote but I'm afraid that it would sum them by customer_id. How do I avoid this mistake of double accounting? Thanks in advance!
WITH example AS(SELECT
customer_id
,MAX(nvl(promised_arrival_day, ship_day)) OVER (PARTITION BY purchase_id) AS ship2_day
,purchase_id
,SUM(price) AS order_size
FROM
my_table
GROUP BY
customer_id
,MAX(nvl(promised_arrival_day, ship_day)) OVER (PARTITION BY customer_purchase_id)
,purchase_id)
SELECT
example.customer_id
,TO_CHAR(example.ship2_day + (7-TO_CHAR(example.ship2_day,'d')),'MM-DD-YYYY') AS week_ending
,example.purchase_id
,example.order_size
FROM
example;
Just
SELECT customer_id, purchase_id, sum(price)
FROM your_table
GROUP BY customer_id, purchase_id
Each record will be counted only once. It doesn't do any "double accounting" as you say.
You will get one record for each unique combination of customer_id/puchase_id in your data.
Looking at your data, I would do something like.
with tbl as(
-- query by which you are getting dataset in example
)
select customer_id,purchase_id, sum(price) as total_price from tbl
group by purchase_id,customer_id

Display each duplicate entry

Using Oracle Application Express and I want to display each duplicate entry in a table. I also want to create a column with a value of 1 for each instance of a duplicate.
So with a table:
Name
Chris
Sean
Chris
John
My query should return
Name Count
Chris 1
Chris 1
How would I do this?
You can do this using window/analytic functions:
select name, 1
from (select name, count(*) over (partition by name) as cnt
from table t
) t
where cnt > 1;

Grouping data by date ranges

I wonder how do I select a range of data depending on the date range?
I have these data in my payment table in format dd/mm/yyyy
Id Date Amount
1 4/1/2011 300
2 10/1/2011 200
3 27/1/2011 100
4 4/2/2011 300
5 22/2/2011 400
6 1/3/2011 500
7 1/1/2012 600
The closing date is on the 27 of every month. so I would like to group all the data from 27 till 26 of next month into a group.
Meaning to say I would like the output as this.
Group 1
1 4/1/2011 300
2 10/1/2011 200
Group 2
1 27/1/2011 100
2 4/2/2011 300
3 22/2/2011 400
Group 3
1 1/3/2011 500
Group 4
1 1/1/2012 600
It's not clear the context of your qestion. Are you querying a database?
If this is the case, you are asking about datetime but it seems you have a column in string format.
First of all, convert your data in datetime data type (or some equivalent, what db engine are you using?), and then use a grouping criteria like this:
GROUP BY datepart(month, dateadd(day, -26, [datefield])), DATEPART(year, dateadd(day, -26, [datefield]))
EDIT:
So, you are in Linq?
Different language, same logic:
.GroupBy(x => DateTime
.ParseExact(x.Date, "dd/mm/yyyy", CultureInfo.InvariantCulture) //Supposed your date field of string data type
.AddDays(-26)
.ToString("yyyyMM"));
If you are going to do this frequently, it would be worth investing in a table that assigns a unique identifier to each month and the start and end dates:
CREATE TABLE MonthEndings
(
MonthID INTEGER NOT NULL PRIMARY KEY,
StartDate DATE NOT NULL,
EndDate DATE NOT NULL
);
INSERT INTO MonthEndings VALUES(201101, '27/12/2010', '26/01/2011');
INSERT INTO MonthEndings VALUES(201102, '27/01/2011', '26/02/2011');
INSERT INTO MonthEndings VALUES(201103, '27/02/2011', '26/03/2011');
INSERT INTO MonthEndings VALUES(201112, '27/11/2011', '26/01/2012');
You can then group accurately using:
SELECT M.MonthID, P.Id, P.Date, P.Amount
FROM Payments AS P
JOIN MonthEndings AS M ON P.Date BETWEEN M.StartDate and M.EndDate
ORDER BY M.MonthID, P.Date;
Any group headings etc are best handled out of the DBMS - the SQL gets you the data in the correct sequence, and the software retrieving the data presents it to the user.
If you can't translate SQL to LINQ, that makes two of us. Sorry, I have never used LINQ, so I've no idea what is involved.
SELECT *, CASE WHEN datepart(day,date)<27 THEN datepart(month,date)
ELSE datepart(month,date) % 12 + 1 END as group_name
FROM payment

Select all rows from SQL based upon existence of multiple rows (sequence numbers)

Let's say I have table data similar to the following:
123456 John Doe 1 Green 2001
234567 Jane Doe 1 Yellow 2001
234567 Jane Doe 2 Red 2001
345678 Jim Doe 1 Red 2001
What I am attempting to do is only isolate the records for Jane Doe based upon the fact that she has more than one row in this table. (More that one sequence number)
I cannot isolate based upon ID, names, colors, years, etc...
The number 1 in the sequence tells me that is the first record and I need to be able to display that record, as well as the number 2 record -- The change record.
If the table is called users, and the fields called ID, fname, lname, seq_no, color, date. How would I write the code to select only records that have more than one row in this table? For Example:
I want the query to display this only based upon the existence of the multiple rows:
234567 Jane Doe 1 Yellow 2001
234567 Jane Doe 2 Red 2001
In PL/SQL
First, to find the IDs for records with multiple rows you would use:
SELECT ID FROM table GROUP BY ID HAVING COUNT(*) > 1
So you could get all the records for all those people with
SELECT * FROM table WHERE ID IN (SELECT ID FROM table GROUP BY ID HAVING COUNT(*) > 1)
If you know that the second sequence ID will always be "2" and that the "2" record will never be deleted, you might find something like:
SELECT * FROM table WHERE ID IN (SELECT ID FROM table WHERE SequenceID = 2)
to be faster, but you better be sure the requirements are guaranteed to be met in your database (and you would want a compound index on (SequenceID, ID)).
Try something like the following. It's a single tablescan, as opposed to 2 like the others.
SELECT * FROM (
SELECT t1.*, COUNT(name) OVER (PARTITION BY name) mycount FROM TABLE t1
)
WHERE mycount >1;
INNER JOIN
JOIN:
SELECT u1.ID, u1.fname, u1.lname, u1.seq_no, u1.color, u1.date
FROM users u1 JOIN users u2 ON (u1.ID = u2.ID and u2.seq_no = 2)
WHERE:
SELECT u1.ID, u1.fname, u1.lname, u1.seq_no, u1.color, u1.date
FROM users u1, thetable u2
WHERE
u1.ID = u2.ID AND
u2.seq_no = 2
Check out the HAVING clause for a summary query. You can specify stuff like
HAVING COUNT(*) >= 2
and so forth.

Resources