Oracle : Date Checking is used last 6months or not - oracle

I have table "CONTACT", if contact createddate is not used last 6 months in some other table i need to remove the Contact, can anyone help to resolve this?

If you want to identify contacts that have not had an order in the last 6 months
select c.contact_id
from contact c
where not exists( select 1
from orders o
where o.contact_id = c.contact_id
and o.order_date > add_months(sysdate,-6) )
To delete the rows
delete from contact c
where not exists( select 1
from orders o
where o.contact_id = c.contact_id
and o.order_date > add_months(sysdate,-6) )
That being said, it seems unlikely that you'd want to do this. If you have a reasonable data model, deleting a contact would mean that you had to delete any order older than 6 months which seems like a bad idea. Perhaps it would make more sense to set an active_flag to 'N' in that case.

Related

Consolidate rows

I'm trying to cut down on rows a report has. There are 2 assets that return on this query but I want them to show up on one row.
Basically if dc.name LIKE '%CT/PT%' then I want it to be same row as the asset. The SP.SVC_PT_ID is the common field to join them.
There will be times when there is no dc.name LIKE '%CT/PT%' however I still want the DV.MFG_SERIAL_NUM to populated just with a Null to the right.
Select SP.SVC_PT_ID, SP.DEVICE_ID, DV.MFG_SERIAL_NUM, dc.name,
substr(dc.name,26)
From EIP.SVC_PT_DEVICE_REL SP,
eip.device_class dc,
EIP.DEVICE DV
Where SP.EFF_START_TIME < To_date('20170930', 'YYYYMMDD') + 1
and SP.EFF_END_TIME is null
and dc.id = DV.device_class_id
and DV.ID = SP.device_id
ORDER BY SP.SVC_PT_ID, DV.MFG_SERIAL_NUM;
I'm not sure I understand what you are saying; test case would certainly help. You said that query you posted returns two rows (only if we saw which ones ...) but you want them to be displayed as the image you attached to the message.
Generally speaking, you can do that using an aggregate function (such as MAX) on certain column(s), along with the GROUP BY clause that contains the rest of them.
Just for example:
select svc_pt_id, max(ctpt_name) ctpt_name, sum(ctpt_multipler) ctpt_multipler
from ...
group by svc_pt_id
As I said: a test case would help people who'd want to answer the question. True - someone might have understood it far better than I did and will provide assistance nevertheless.
EDIT: after you posted sample data (which, by the way, don't match screenshot you posted previously), maybe something like this might do the job: use analytic function to check whether name contains CT/PT; if so, take its data. Otherwise, display both rows.
SQL> with test as (
2 select 14 svc_pt_id, 446733 device_id, 'Generic Electric' name from dual union
3 select 14, 456517, 'Generic CT/PT, Multiplier' from dual
4 ),
5 podaci as
6 (select svc_pt_id, device_id, name,
7 rank() over (partition by svc_pt_id
8 order by case when instr(name, 'CT/PT') > 1 then 1
9 else 2
10 end) rnk
11 from test
12 )
13 select svc_pt_id, device_id, name
14 from podaci
15 where rnk = 1;
SVC_PT_ID DEVICE_ID NAME
---------- ---------- -------------------------
14 456517 Generic CT/PT, Multiplier
SQL>
My TEST table (created by WITH factoring clause) would be the result of your current query.

How to return names of events scheduled on the same date at the same location as 'JOHN BIRTHDAY'

I got this question in the exam wrong, and I want to know how to fix it? How to return names of events scheduled on the same date at the same location as 'JOHN BIRTHDAY'?
Select ename from event e1, location L where e1.LID=L.LID AND
E1.ENAME='JOHN BIRTHDAY' AND E1.START_DATE=DATE'2017-01-02';
EVENT TABLE: LID= LOCATION ID , AND MID = MEMBER ID
EID ENAME MID LID START_DAT END_DATE
1 JOHN BIRTHDAY 1 2 02-JAN-17 02-JAN-17
2 SAMI BIRTHDAY 2 1 02-JAN-17 02-JAN-17
4 THANKSGIVING 2 2 02-JAN-17 02-JAN-17
3 SUSAN GRADUATION 1 2 02-JAN-17 02-JAN-17
What you did wrong...
You are looking up data in two tables, EVENT and LOCATION. You match them by LOCATION_ID - no harm there. But then, from EVENT you select just one row: the row where ENAME = 'JOHN BIRTHDAY'. Then the first mistake: to that, you add "and START_DATE - ..." No need for that; you already limited the rows from the EVENT table to the row with ENAME = 'JOHN BIRTHDAY'.
Then: you are joining to LOCATION for absolutely no reason; you are not selecting anything from LOCATION. (Nor do you need to, since the problem is asking you to find other events that share the same location, meaning the same LOCATION_ID, and that is already available in the EVENT table.)
The biggest mistake: nowhere in your code are you looking for OTHER events. With some constraints: same date and location as 'JOHN BIRTHDAY', but that is irrelevant since you are not looking for ANY other events, anywhere in the code.
How to solve this problem correctly:
You need to look up data in EVENT twice. One time to find out when and where 'JOHN BIRTHDAY' will be. (It is not stated in the problem, but the convention during an exam is that you are not supposed to read the date and location in the table, write them down, and then hard-code them in your query; instead, they should be "variables" in the solution.) Second time you need to look IN THE SAME TABLE to find other events with the same date and location.
So this means you will need to join EVENT to itself (give it two different aliases, so you can refer to them clearly - "this" copy vs. "that" copy of the table). Join them by LID and ... date ... but that's more complicated (see below). Select the ENAME from one copy, while in the other copy put the WHERE condition: where ENAME = 'JOHN BIRTHDAY'.
Something like
select e1.ename
from event e1 join event e2 on e1.lid = e2.lid and e1.start_date = e2.start_date
where e2.ename = 'JOHN BIRTHDAY'
;
which is what Darzen posted in a different Answer before I typed mine.
This may be all you need, except for the following interesting question. The base data has a START_DATE and an END_DATE, not just a straight DATE. Does that mean that an event may be from 9 AM to noon, while 'JOHN BIRTHDAY' is from 6 PM to 8:30 PM? Or perhaps, does it mean that some events may extend for two or three days, and you need to find all those that overlap with 'JOHN BIRTHDAY'?
That makes the problem more interesting, but let's leave it alone; what I shared with you so far may suffice.
Final note - you may be better off learning modern (SQL Standard) notation for joins. You used Oracle syntax, which is not wrong, but it is not the best option.
select b.ename
from events a ,
(select ename, lid, start_Date from events) b
where a.lid = b.lid and a.start_date = b.start_date
and a.ename = 'JOHN BIRTHDAY' and b.ename <> 'JOHN BIRTHDAY';
Looks to me like
WITH cteJOHN_BIRTHDAY AS (SELECT *
FROM EVENT
WHERE ENAME = 'JOHN BIRTHDAY')
SELECT e.ENAME
FROM EVENT e
INNER JOIN cteJOHN_BIRTHDAY j
ON j.START_DAT = e.START_DAT AND
j.LID = e.LID AND
j.EID <> e.EID
ought to do it.
Not tested on animals - you'll be first! :-)

Removing duplicate columns in one row while merging corresponding column values

Apologies if this seems simple to some, I am still in the (very) early stages of learning!
Basically I've got a table database that has multiple users (Users_ID), each with a corresponding access name(NAME). The problem is, some Users have multiple access names, meaning when the data is pulled, there is duplicates in the User_ID column.
I need to remove the duplicates in the User column and join their corresponding access names in the NAME column, so it only takes up 1 row and no data is lost.
The current SQL query I'm using is :
select Table1_user_id, Table2.name,
from Table1
inner join Table2
on Table1.role_id = Table2.role_id
An example of what this would return:
USER_ID | NAME
------- --------------
Tim Level_1 Access
John Level 2 Access
Tim Level 2 Access
Mark Level 3 Access
Tim Level 3 Access
Ideally, I would remove the duplicates for Tim and display as following:
USER_ID | NAME
------- ----------------------------------------------
Tim Level_1 Access, Level 2 Access, Level 3 Access
John Level 2 Access
Mark Level 3 Access
Thanks in advance for any help regarding this and sorry if something similar has been asked before!
Use GROUP_CONCAT with SEPARATOR :
SELECT Table1.user_id, GROUP_CONCAT(Table2.name SEPARATOR ',') AS Ename
FROM Table1
INNER JOIN Table2 ON Table1.role_id = Table2.role_id
GROUP BY Table1.user_id
select Table1_user_id, LISTAGG(Table2.name,', ') WITHIN GROUP (ORDER BY Table2.name) as Name
from Table1
inner join Table2
on Table1.role_id = Table2.role_id

update rows from multiple tables

I have two tables affiliation and customer, in that i have data like this
aff_id From_cus_id
------ -----------
1 10
2 20
3 30
4 40
5 50
cust_id cust_aff_id
------- -------
10
20
30
40
50
i need to update data for cust_aff_id column from affiliation table which is aff_id like below
cust_id cust_aff_id
------- -------
10 1
20 2
30 3
40 4
50 5
could u please give reply if anyone knows......
Oracle doesn't have an UPDATE with join syntax, but you can use a subquery instead:
UPDATE customer
SET customer.cust_aff_id =
(SELECT aff_id FROM affiliation WHERE From_cus_id = customer.cust_id)
merge into customer t2
using affiliation t1 on (t1.From_cus_id =t2.cust_id )
WHEN MATCHED THEN
update set t2.cust_aff_id = t1.aff_id
;
Here is an update with join syntax. This, quite reasonably, works only if from_cus_id is primary key in the first table and cust_id is foreign key in the second table, referencing the first table. Without these conditions, the requirement doesn't make much sense in the first place anyway... but Oracle requires that these constraints be stated explicitly in the tables. This is also reasonable on Oracle's part IMO.
update
( select t1.aff_id, t2.cust_aff_id
from affiliation t1 join customer t2 on t2.cust_id = t1.from_cus_id) j
set j.cust_aff_id = j.aff_id;

Delete row with the use of Max(Date)?

I'm trying to delete some members from their table based on their rental date. If they havent rented for more than 3 years they can be deleted. The issue i am facing is that some members have rented recently, meaning the query still pulls their ID up and deletes ALL data because there is a date on their record indicating the DateOut value of greater than 3 years.
delete from (select *
from rental
inner join member
on rental.member_id = member.member_id
inner join rental_line
on rental.rental_id = rental_line.rental_id
where months_between(sysdate, dateout) > ( 36 ));
delete from member
where exists(select dateout
from rental
where member.member_id = rental.member_id
and months_between(sysdate, rental.dateout) > ( 36 ));
These are the two scripts i am running to delete the data, it is pulled out from rental first and their is a ON CASCADE within the foreign key which also pulls the data from the Rental_Line table.
Then the second query runs to delete the data from the member table freely as there isn't any integrity issues due to the corresponding data being removed previously from the linked tables.
Delete from rental r where r.member_id in (
select i.member_id
from rental i
group by i.member_id
having MONTHS_BETWEEN(sysdate, max(dateout))>(36)
);
DELETE FROM Member where not exists(
Select *
from rental
where Member.Member_ID = Rental.Member_ID
);
You just finished deleting all of the rental records, unless you keep an archive, you are just looking for members without rentals at all. If this is not the case, you will need to make a temporary holding table for member_id's that were purged.

Resources