Oracle: remove duplicates from select results in specific columns - oracle

I need to create a view contains BSB#, customer#, name from customer, and account#, type, balance from account.
I tried this select statement:
select customer.bsb#, customer.customer#, customer.name, account.account#, account.type, account.balance
from customer
left outer join account on customer.bsb# = account.bsb#
and customer.customer# = account.customer#;
And the output is like this:
output
However, I need to make the out like:
display
So, how could I remove the duplicate results from certain columns?

Related

Update lead time for one location based on item another location

I'm trying to set up a query for testing some software and need to adjust some data on the tables. In short, for all items that are located at factory A, then I want to update the lead times(int) for those items at all other factories to be equal to the lead time at factory A.
The end result I'm expecting would be for any item produced at factory A to have the same lead time no matter where it is located.
edit: Lets call the table "PRODUCTION"
Operation has "item", "location", and "leadtime" as fields.
What I've tried is to select a subquery of items at factory A and use that as a join back against the table to select the items.
select
product,
location,
leadtime
from production join
(
select product from production
where location = 'F01'
) as a
on item = a.item
where location not like 'F01'
I assume you are getting the error message ORA-00933: SQL command not properly ended because Oracle does not support AS for subquery aliases. Also, it looks like item = a.item might lead to an ambiguous error message.
Since the product is optionally present in a different location, this sounds like a LEFT JOIN. And NVL lets you use the other factory leadtime, if it exists, else use the existing leadtime.
Try this query:
select
production.product,
production.location,
nvl(a.leadtime, production.leadtime) leadtime
from production
left join
(
select item, leadtime
from production
where location = 'F01'
) a
on production.item = a.item
where location <> 'F01';

Better solution than left join subqueries?

TablePatient.Patient_ID(PK)
TableProviders.Encounter (joins to PK)
TableProviders.Provider_Type
TableProviders.Provider_ID
TableNames.Full_Name
TableNames.Provider_ID (joins to Table Names)
I want a query that will give, for all the Patient_IDs, the Full_Name of the provider for every Provider ID.
There are about 30 provider_types.
I have made this already using a left join a ton of left joins. It takes a long time to run and I am thinking there is a trick I am missing.
Any help?
Ok, my previous answer didn't match at all what you meant. You want to pivot the table to have on each line one Patient_ID with every Full_name for every provider_type. I assume that each patient has only one provider for one type and not more ; if more, you will have more than one row for each patient, and anyway I don't think it's really possible.
Here is my solution with pivot. The first part is to make it more understandable, so I create a table named TABLE_PATIENT in a subquery.
WITH TABLE_PATIENT AS
(
SELECT TablePatient.Patient_ID,
TableProviders.Provider_Type,
TableNames.Full_Name
FROM TablePatient LEFT JOIN
TableProviders on TablePatient.Patient_ID = TableProviders.Encounter
LEFT JOIN
TableNames on TableNames.Provider_ID = TableProviders.Provider_ID
group by TablePatient.Patient_ID,
TableProviders.Provider_Type,
TableNames.Full_Name
)
SELECT *
FROM TABLE_PATIENT
PIVOT
(
min(Full_name)
for Provider_type in ([type1], [type2],[type3])
) AS PVT
So TABLE_PATIENT just has many rows for each patient, with one provider each row, and the pivot puts everything on a single row. Tell me if something doesn't work.
You need to write every type you want in the [type1],[type2] etc. Just put them inside [], no other character needed as ' or anything else.
If you put only some types, then the query will not show providers of other types.
Tell me if something doesn't work.
If I understand what you mean, you just want to group the answer by Patient Id and then Provider ID. A full name is unique on a provider id right ?
This should be something like
SELECT TablePatient.Patient_ID,
TableProviders.Provider_ID,
TableNames.Full_Name
FROM TablePatient LEFT JOIN
TableProviders on TablePatient.Patient_ID = TableProviders.Encounter
LEFT JOIN
TableNames on TableNames.Provider_ID = TablerProviders.Provider_ID
group by TablePatient.Patient_ID,
TableProviders.Provider_ID,
TableNames.Full_Name
You can either group by TableNames.Full_Name or select First(TableNames.Full_Name) for example if indeed a full name is unique to a provider ID.
Note : I used the SQL server Syntax, there can be différences with Oracle ..

ORACLE Select list inconsistant with group by

I can't create my view and I don't know how to fix it.
when trying to create the view it tries to add all the columns from select to the group by, which isn't what I want. and doesn't work anyways
CREATE OR REPLACE FORCE VIEW CustomerSaleHistoryView AS
Select SALE.SaleID,
SALE.SaleDate,
CUSTOMER.LastName,
CUSTOMER.FirstName,
SALE_ITEM.SaleItemID,
SALE_ITEM.ItemID,
ITEM.ItemPrice,
SUM(SALE_ITEM.ITEMPRICE),
AVG(SALE_ITEM.ITEMPRICE)
from customer
join sale on customer.CUSTOMERID = Sale.CUSTOMERID
join sale_item on sale_item.saleid = sale.saleID
join item on sale_item.itemID = item.itemID
group by CUSTOMER.LastName, CUSTOMER.FirstName, SALE.SaleID;
In order for you query to work you MUST group by any columns that are not being aggregated with a formula like SUM() or AVG(). In your case GROUP BY SALE.SaleID, SALE.SaleDate, CUSTOMER.LastName, CUSTOMER.FirstName, SALE_ITEM.SaleItemID, SALE_ITEM.ItemID, ITEM.ItemPrice
What are you trying to accomplish that you don't believe this GROUP BY is appropriate?
When using group by clause the list of columns that you are selecting should be either part of the group by clause or they should be part of an aggregate function. In your case SALE.SaleDate, SALE_ITEM.SaleItemID, SALE_ITEM.ItemID and ITEM.ItemPrice doesn't satisfy that rule. You need to include these to your group by clause. Once you fix the select statement and when it returns the desired output convert that into a view.

Need to select column from subquery into main query

I have a query like below - table names etc. changed for keeping the actual data private
SELECT inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
I am selecting records from Invoice based on Order. i.e. all records from Invoice which are common with order records for today, based on those 3 columns...
Now I want to select Order_Num from Order in my select query as well.. so that I can use the whole thing to insert it into totally seperate table, let's say orderedInvoices.
insert into orderedInvoices(seq_no,..same columns as Inv...,Cr_dt)
(
SELECT **Order.Order_Num**, inv.*,TRUNC(sysdate)
FROM Invoice inv
WHERE (inv.carrier,inv.pro,inv.ndate) IN
(
SELECT carrier,pro,n_dt FROM Order where TRUNC(Order.cr_dt) = TRUNC(sysdate)
)
)
?? - how to do I select that Order_Num in main query for each records of that sub query?
p.s. I understand that trunc(cr_dt) will not use index on cr_dt (if a index is there..) but I couldn't select records unless I omit the time part of it..:(
If the table ORDER1 is unique on CARRIER, PRO and N_DT you can use a JOIN instead of IN to restrict your records, it'll also enable you to select whatever data you want from either table:
select order.order_num, inv.*, trunc(sysdate)
from Invoice inv
join order ord
on inv.carrier = ord.carrier
and inv.pro = ord.pro
and inv.ndate = ord.n_dt
where trunc(order.cr_dt) = trunc(sysdate)
If it's not unique then you have to use DISTINCT to deduplicate your record set.
Though using TRUNC() on CR_DT will not use an index on that column you can use a functional index on this if you do need an index.
create index i_order_trunc_cr_dt on order (trunc(cr_dt));
1. This is a really bad name for a table as it's a keyword, consider using ORDERS instead.

Active Record Join with most recent association object attribute

I have a Contact model which has many Notes. On one page of my app, I show several attributes of a table of contacts (name, email, latest note created_at).
For the note column, I'm trying to write a joins statement that grabs all contacts along with just their latest note (or even just the created_at of it
What I've come up with is incorrect as it limits and orders the contacts, not their notes:
current_user.contacts.joins(:notes).limit(1).order('created_at DESC')
If you just want the created_at value for the most recent note for each contact, you can first create a query to find the max value and then join with that query:
max_times = Note.group(:contact_id).select("contact_id, MAX(created_at) AS note_created_at").to_sql
current_user.contacts.select("contacts.*, note_created_at").joins("LEFT JOIN (#{max_times}) max_times ON contacts.id = max_times.contact_id")
If you want to work with the Note object for the most recent notes, one option would be to select the notes and group them by the contact_id. Then you can read them out of the hash as you work with each Contact.
max_times = Note.group(:contact_id).select("contact_id, MAX(created_at) AS note_created_at").to_sql
max_notes = Note.select("DISTINCT ON (notes.contact_id) notes.*").joins("INNER JOIN (#{max_times}) max_times ON notes.contact_id = max_times.contact_id AND notes.created_at = note_created_at").where(contact_id: current_user.contact_ids)
max_notes.group_by(&:contact_id)
This uses DISTINCT ON to drop dups in case two notes have exactly the same contact_id and created_at values. If you aren't using PostgreSQL you'll need another way to deal with dups.

Resources