How to run SQL query group by issue? - oracle

I have a table with columns :
Table Name: IdentityTable
ID Dest_Name Dest_Reference_Id Format IG
31231231 India Delhi XKHYGUI 21
12313131 USA Washington XHKOWKG 1
34645542 India Mumbai XKLWOFH 1
31231314 USA California XLGJDJG 21
31234531 India Delhi XKHIHUI 21
12375671 USA Washington XHKLHKG 21
12574613 USA Washington XLKWMKG 1
and so on...
I want to query this table to retrieve information in this form:
Dest_Name Dest_Reference_Id Total_Format Format IG
India Delhi 2 XKHYGUI 21
India Delhi 2 XKHIHUI 21
USA Washington 3 XHKOWKG 1
USA Washington 3 XHKLHKG 21
USA Washington 3 XLKWMKG 1
India Mumbai 1 XKLWOFH 1
USA California 1 XLGJDJG 21
I did:
select dest_name, dest_reference_id, count (format)
from IdentityTable
Group By dest_name, dest_reference_id;
I could retrieve all information required except Format column in the result. How should I modify my query to return expected result ?

Make two sub-queries and join em up.
SELECT counts.dest_name,
counts.dest_reference_id,
counts.total_format,
idents.format,
idents.IG
FROM
(
select dest_name, dest_reference_id, count (format) as total_format
from IdentityTable
Group By dest_name, dest_reference_id;
) counts
join
(
select distinct dest_name, dest_reference_id, format, IG
from identitytable
) idents
on counts.dest_name = idents.dest_name
and counts.dest_reference_id = idents.dest_reference_id

count(*) over(partition by dest_name, dest_reference_id)
and without a group by. google "oracle analytic functions".

Related

How to categorize data in a ORACLE table based on a primary key?

I have a table TRAVEL with column TRIP_ID as primary key.
SOURCE DATA
TRIP_ID PERSON_NAME DESTINATION SOURCE TRANSACTION_ID TRIP_COUNT
100 Mike London Zurich 1000B112 1
101 Mike Paris Capetown 1000B112 1
102 Mike Moscow Madrid 1000B112 1
103 John Delhi Moscow 1100A110 1
104 John Toronto Zurich 1100A110 1
105 Mary Chennai Madrid 1100A111 1
106 Mary Berlin Zurich 1100A111 1
EXPECTED RESULTS:
when I do select * from TRAVEL where TRANSACTION_ID = 1100A111 it returns below two rows as below .
so I want my data to be categorized based on the transaction_ID on a run time.I dont want to hardcode the value for transaction-ID each time as above but i want to group it in such a way that it should fetch me the above expected results.I mean it should return all the data which are corresponding to the TransactionID in the table and it should not sum up the TRIP COUNT.It should return me the rows as below in my table.I am ok to create view .Please suggest
TRIP_ID PERSON_NAME DESTINATION SOURCE TRANSACTION_ID TRIP_COUNT
105 Mary Chennai Madrid 1100A111 1
106 Mary Berlin Zurich 1100A111 1
Can someone suggest a query in ORACLE to handle this ? I donot want to hardcode transaction ID
Regards
Sameer

Count all data even with zero/0 value

I have data like this
product location
snack america
snack brazil
biscuit america
biscuit china
biscuit japan
soda brazil
soda japan
soda india
what I want is like below, however I can do it differently using pivot, but is is possible to have the data like this?
location product count
america snack 1
america biscuit 1
america soda 0
brazil snack 1
brazil biscuit 0
brazil soda 1
japan snack 0
japan biscuit 1
japan soda 1
We can generate a "calendar" table of all product/location combinations, via a cross join:
SELECT
loc.location,
prod.product,
CASE WHEN t.location IS NULL THEN 0 ELSE 1 END AS count
FROM (SELECT DISTINCT location FROM yourTable) loc
CROSS JOIN (SELECT DISTINCT product FROM yourTable) prod
LEFT JOIN yourTable t
ON t.location = loc.location AND
t.product = prod.product
ORDER BY
loc.location,
prod.product;
Demo
Please elaborate our concern, the result table that you are asking could be generated but specify your concern in a detail manner

Oracle Query Prevent Displayed Duplicate Record

Let's say i have a table structure like this :
ID | Name | SCHOOLNAME | CODESCHOOL
1 DARK Kindergarten 123 1
2 DARK Kindergarten 111 1
3 Knight NY University 3
4 Knight LA Senior HS 2
5 JOHN HARVARD 3
so, how to diplay all of the data above into like this :
ID | Name | SCHOOLNAME | CODESCHOOL
1 DARK Kindergarten 123 1
3 Knight NY University 3
5 JOHN HARVARD 3
my purpose is want to display data with the max of codeschool, but when i tried with my query below :
SELECT NAME, SCHOOLNAME, MAX(CODESCHOOL) FROM TABLE GROUP BY NAME, SCHOOLNAME
but the result is just like this :
ID | Name | SCHOOLNAME | CODESCHOOL
1 DARK Kindergarten 123 1
2 DARK Kindergarten 111 1
3 Knight NY University 3
4 Knight LA Senior HS 2
5 JOHN HARVARD 3
maybe it caused by the GROUP BY SCHOOLNAME, when i tried to not select SCHOOLNAME, the data displayed just like what i expected, but i need the SCHOOLNAME field for search condition in my query
hope you guys can help me out of this problem
any help will be appreciated
thanks
Using some wacky joins you can get a functional get max rows per category query.
What you essentially need to do is to join the table to itself and make sure that the joined values only contain the top values for the CODESCHOOL column.
I've also added a :schoolname parameter because you wanted to search by schoolname
Example:
SELECT
A.*
FROM
TABLE1 A
LEFT OUTER JOIN TABLE1 B ON B.NAME = A.NAME
AND B.CODESCHOOL < A.CODESCHOOL
WHERE
B.CODESCHOOL IS NULL AND
(
(A.SCHOOLNAME = :SCHOOLNAME AND :SCHOOLNAME IS NOT NULL) OR
(:SCHOOLNAME IS NULL)
);
this should create this output, note that dark has 2 outputs because it has 2 rows with the same code school which is the max in the dark "category"/name.
ID|NAME |SCHOOLNAME |CODESCHOOL
--| -----|----------------|----------
4|Knight|LA Senior HS | 2
5|JOHN |HARVARD | 3
2|DARK |Kindergarten 111| 1
1|DARK |Kindergarten 123| 1
It's not the most effective query but it should be more than good enough as a starting point.
Sidenote: I've been blatantly stealing this logic for a while from https://www.xaprb.com/blog/2007/03/14/how-to-find-the-max-row-per-group-in-sql-without-subqueries/
I am using an analytical window function ROW_NUMBER().
This will group (or partition) by NAME then select the top 1 CODESCHOOL in DESC order.
Select NAME,
SCHOOLNAME,
CODESCHOOL
From (
Select NAME,
SCHOOLNAME,
CODESCHOOL,
ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY CODESCHOOL DESC) as rn
from myTable)
Where rn = 1;

Select same column for different values on a different column

I did search the forum before posting this and found some topics which were close to the same issue but I still had questions so am posting it here.
EMP_ID SEQ_NR NAME
874830 3 JOHN
874830 4 JOE
874830 21 MIKE
874830 22 BILL
874830 23 ROBERT
874830 24 STEVE
874830 25 JERRY
My output should look like this.
EMP ID SEQ3NAME SEQ4NAME SEQ21NAME SEQ22NAME SEQ23NAME SEQ24NAME SEQ25NAME
874830 JOHN JOE MIKE BILL ROBERT STEVE JERRY
SELECT A.EMP_ID
,A.NAME SEQ3NAME
,B.NAME SEQ4NAME
FROM AC_XXXX_CONTACT A
INNER JOIN AC_XXXX_CONTACT B ON A.EMP_ID = B.EMP_ID
WHERE A.SEQ_NR = '03' AND B.SEQ_NR = '04'
AND B.EMP_ID = '874830';
The above query helped me get the below results.
EMP_ID SEQ3NAME SEQ4NAME
874830 JOHN JOE
My question is to get all the fields(i.e till seq nr = 25) should I be joining the table 5 more times.
Is there a better way to get the results ?
I m querying against the Oracle DB
Thanks for your help.
New Requirement
New Input
STU-ID SEM CRS-NBR
12345 1 100
12345 1 110
12345 2 200
New Output
stu-id crs1 crs2
12345 100 200
12345 110
Not tested since you didn't provide test data (from table AC_XXXX):
(using Oracle 11 PIVOT clause)
select *
from ( select emp_id, seq_nr, name
from ac_xxxx
where emp_id = '874830' )
pivot ( max(name) for seq_nr in (3 as seq3name, 4 as seq4name, 21 as seq21name,
22 as seq22name, 23 as seq23name, 24 as seq24name, 25 as seq25name)
)
;
For Oracle 10 or earlier, pivoting was done "by hand", like so:
select max(emp_id) as emp_id, -- Corrected based on comment from OP
max(case when seq_nr = 3 then name end) as seq3name,
max(case when seq_nr = 4 then name end) as seq4name,
-- etc. (similar expressions for the other seq_nr)
from ac_xxxx
where emp_id = '874830'
;
Or, emp_id doesn't need to be within max() if we add group by emp_id - which then will work even without the WHERE clause, for a different but related question.

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