Join two tables based on a criteria of string content in Table 1 - oracle-sqldeveloper

I have two tables which I'm joining by matching "some_name" of Table_A with "j_name" of Table_B. In few cases, I would like to join based on below criteria:
if for example string "AB-FBb3" is found in Table_A, then I would like to match it against a specific value of "QT001" in Table_B.
Is this possbile?
Table_A:
**AB some_name G_NAME Status some_time**
------------------------------------------------------------
AAA Job1 xxxxxxxxx Ended OK 2020-06-29 10:37:52
AAA AB-Jobd xxxxxxxxx Ended OK 2020-06-29 10:37:52
BBB AB-ADu001 xxxxxxxxx Ended OK 2020-06-29 10:37:52
BBB AB-Job2 xxxxxxxxx Ended OK 2020-06-29 10:37:52
BBB AB-FBb3 xxxxxxxxx Ended OK 2020-06-29 10:37:52
Table_B:
**RM j_name desc rand_time**
----------------------------------------------------
111 AB-Job2 Sometext 2020-06-29 06:30:51
111 AB-Job5 Sometext1 2020-06-29 09:31:52
222 LLu001 Sometext2 2020-06-29 09:34:11
222 QT001 Sometext4 2020-06-29 11:32:23
222 BMX-Jobd Sometext4 2020-06-29 11:32:23
What I have so far, to which I would like to append the above condition as well:
SELECT a.some_name,a.some_time, b.desc
FROM Table_A a
LEFT JOIN Table_B b
ON
(b.j_name IN (a.service_name, 'LL' || SUBSTR(a.some_name, instr(a.some_name, 'AD')+2 ,4)))
or
(b.j_name IN (a.service_name, 'BMX-' || a.some_name))
where a.some_name like 'AB-%' order by log_time desc

That seems to be a rather unpleasant problem.
I can't see from your example where there is any logic to the renaming; it appears to be simply a hard-coded list of replacements.
I'd go with something like:
SELECT *
FROM (
SELECT some_name,
CASE some_name
WHEN 'AB-FBb3' THEN 'QT001'
-- etc.
ELSE some_name
END AS j_name
FROM Table_A
) AS a
FULL OUTER JOIN Table_B b ON a.j_name = b.j_name
because the CASE in the subquery makes it easy to see the re-namings.

Related

Removing duplicates based on one value

customer id name Pay_type
1111 aaaa regular
1111 aaaa late
1111 aaaa regular
1111 aaaa regular
2222 bbbb regular
2222 bbbb regular
2222 bbbb regular
3333 cccc regular
3333 cccc late
4444 dddd regular
4444 dddd regular
I have a SQL query that gives me the above result and I want the result to remove any customer that has a late fee
the output needs to be:
customer id name Pay_type
2222 bbbb regular
2222 bbbb regular
2222 bbbb regular
4444 dddd regular
4444 dddd regular
select
distinct a.customer_id,
a.name,
pay_type
from table a
left join table b on a.customer_id= b.id
left join table c on c.id = b.pay_id
where b.status = 'Done
I'd do this as an anti-join:
select *
from table a
where not exists (
select null
from table b
where
a.customer_id = b.customer_id and
b.pay_type = 'late'
)
This has advantages over a distinct or a "not in" approach in that it will stop looking after it finds a match. This should work efficiently for both large and small datasets.
Any solution that uses distinct would have to evaluate the entire dataset and then remove dupes.
I'm not sure exactly what your tables look like, but you could do something like:
WHERE customer_id NOT IN (
SELECT customer_id
FROM table_with_customer_and_pay_type
WHERE pay_type = 'late'
GROUP BY customer_id )
Common Table Expression variation:
WITH orig_result_set AS (
select
distinct a.customer_id,
a.name,
pay_type
from table a
left join table b on a.customer_id= b.id
left join table c on c.id = b.pay_id
where b.status = 'Done'
),
exclude_late_payments AS (
SELECT DISTINCT customer_id
FROM orig_result_set
WHERE pay_type = 'late'
),
on_time_payments AS (
SELECT customer_id,
name,
pay_type
FROM orig_result_set
WHERE customer_id NOT IN exclude_late_payments
)
SELECT *
FROM on_time_payments

Count and list out unique combination by group

I am wanting to derive a SQL that can bring me the following result, but I just can't seem to get my head around this particular scenario.
I want to see how many individual combination of ROLE-combination by USER there are, and report the count and list out role-names.
Here is the example table:
USER ROLE
AAA Report
AAA Enquiry
AAA Manager
BBB Report
BBB Enquiry
BBB Manager
CCC Enquiry
CCC Report
DDD Report
EEE Report
EEE Enquiry
EEE Admin
FFF Report
FFF Enquiry
GGG Report
GGG Enquiry
GGG Manager
GGG PAYROLL
HHH Report
III Report
III Enquiry
There are AAA, and BBB with role combination of "Report-Enquiry-Manager", therefore count of 2 recored.
There is only CCC with Enquiry-Report.
There are DDD and HHH with role of Report.
Therefore, the desired output would be
COUNT ROLE-COMBINATION
2 Report-Enquiry-Manager
3 Enquiry-Report
2 Report
1 Report-Enquiry-Admin
1 Report-Enquiry-Manager-PAYROLL
Could someone point me to the right direction please.
Thanks heaps,
You can user GROUP BY to get Count and use STUFF to get - separated role values.
create table test
(
[USER] varchar(10)
,[Role] varchar(100)
)
insert into test values
('AAA','Report')
,('AAA','Enquiry')
,('AAA','Manager')
,('BBB','Report')
,('BBB','Enquiry')
,('BBB','Manager')
,('CCC','Enquiry')
,('CCC','Report')
,('DDD','Report')
,('EEE','Report')
,('EEE','Enquiry')
,('EEE','Admin')
,('FFF','Report')
,('FFF','Enquiry')
,('GGG','Report')
,('GGG','Enquiry')
,('GGG','Manager')
,('GGG','PAYROLL')
,('HHH','Report')
,('III','Report')
,('III','Enquiry')
select COunt(1) as [COUNT], [Role-Combination] from
(
select Count(1) as [Count], t.[User]
,STUFF((SELECT
'-' + cm.[role] AS [text()]
FROM
test cm
WHERE
cm.[user] = t.[user]
order by [role] desc
FOR XML PATH('')
, root('user'), TYPE).value('.','varchar(max)'), 1, 1, '' )AS [Role-Combination]
from test t
GROUP BY t.[User]
) result
group by result.[Role-Combination]
DROP TABLE test
DECLARE #USER TABLE
(
xUSER VARCHAR(30),
xROLE VARCHAR(30)
)
INSERT INTO #USER (xUSER,xROLE)
VALUES
('AAA','Report'),
('AAA','Enquiry'),
('AAA','Manager'),
('BBB','Report'),
('BBB','Enquiry'),
('BBB','Manager'),
('CCC','Enquiry'),
('CCC','Report'),
('DDD','Report'),
('EEE','Report'),
('EEE','Enquiry'),
('EEE','Admin'),
('FFF','Report'),
('FFF','Enquiry'),
('GGG','Report'),
('GGG','Enquiry'),
('GGG','Manager'),
('GGG','PAYROLL'),
('HHH','Report'),
('III','Report'),
('III','Enquiry')
; WITH x AS
(
SELECT DISTINCT
xUSER,
STUFF((
SELECT '- ' + xRole
FROM #User
WHERE xUser = a.xUSer
ORDER BY xRole
FOR XML PATH ('')
), 1, 1, '') Groups
FROM #User a
)
SELECT
[Cnt] = COUNT(xUser), Groups as [Role-Cmbine]
FROM x
GROUP BY Groups
ORDER BY [Cnt] DESC

How to Use Count as a Criteria in PostgreSQL

I have an existing table1 which contains "account", "tax_year" and other fields. I want to create a table2 with records from table1 when the frequency of CONCAT(account, tax_year) is 1 and meet the WHERE clause.
For instance, if table1 looks like below:
account year
aaa 2014
bbb 2016
bbb 2016
ddd 2014
ddd 2014
ddd 2015
Table2 should be:
account year
aaa 2014
ddd 2015
Here is my script:
DROP TABLE IF EXISTS table1;
CREATE table2 AS
SELECT
account::text,
tax_year::text,
building_number,
imprv_type,
building_style_code,
quality,
quality_description,
date_erected,
yr_remodel,
actual_area,
heat_area,
gross_area,
CONCAT(account, tax_year) AS unq
FROM table1
WHERE imprv_type=1001 and date_erected>0 and date_erected IS NOT NULL and quality IS NOT NULL and quality_description IS NOT NULL and yr_remodel>0 and yr_remodel IS NOT NULL and heat_area>0 and heat_area IS NOT NULL
GROUP BY account,
tax_year,
building_number,
imprv_type,
building_style_code,
quality,
quality_description,
date_erected,
yr_remodel,
actual_area,
heat_area,
gross_area,
unq
HAVING COUNT(unq)=1;
I've spent two days on it but still can't figure out how to make it right. Thank you ahead for your help!
The proper way to use count of pairs (account, tax_year) in table1:
select account, tax_year
from table1
where imprv_type=1001 -- and many more...
group by account, tax_year
having count(*) = 1;
so you should try:
create table table2 as
select *
from table1
where (account, tax_year) in (
select account, tax_year
from table1
where imprv_type=1001 -- and many more...
group by account, tax_year
having count(*) = 1
);
COUNT() = 1 is equivalent to NOT EXISTS(another with the same key fields):
SELECT
account, tax_year
-- ... maybe more fields ...
FROM table1 t1
WHERE NOT EXISTS ( SELECT *
FROM table1 nx
WHERE nx.account = t1.account -- same key field(s)
AND nx.tax_year = t1.tax_year
AND nx.ctid <> t1.ctid -- but a different row!
);
Note: I replaced the COUNT(CONCAT(account, tax_year) concatenation of key fields by a composite match key.

Join three tables and update values to particular table

TableA:
ID RES_ID NAME
--------------------
1 3 (null)
2 1 (null)
3 3 (null)
TableB:
RES_ID AREA_NAME
-------------------
3 India
1 Japan
3 India
TableC:
AREA_NAME CITY_NAME
-----------------------
India Delhi
Japan Tokyo
England London
I want to join the above three tables and update the CITY_NAME in TableC to NAME in TableA using DB2.
Please help me to sort it out.
I have tried the below code but it is not working.
MERGE INTO TableA A
USING TableB B, TableC C
ON A.RES_ID= B.RES_ID
AND B.AREA_NAME = C.AREA_NAME
WHEN MATCHED
THEN UPDATE SET A.NAME = C.CITY_NAME;
It displays error message.I want the output as follows,
Updated TableA:
ID RES_ID NAME
--------------------
1 3 Delhi
2 1 Tokyo
3 3 Delhi
Thanks in advance!
You could try this:
update A set name = c.name from tableA A
inner join tableB B ON A.RES_ID= B.RES_ID
inner join tableC C on B.AREA_NAME = C.AREA_NAME
The MERGE operator is used to update records when the disired record exists otherwise insert the record. But you already have the record, you only need to update a field. Hence you need an update query

sql script to export table's column data to another table's column

Let's say , I have two table with same schema but different data .
Table_A and Table_B .
Table_A
--------
ID(p_key) Number(p_key) Column3 Column4
-----------------------------------------------------
ID1 1 AAA BBB
ID1 2 CCC DDD
ID2 1 EEE FFF
ID2 2 GGG HHH
-
Table_B
--------
ID(p_key) Number(p_key) Column3 Column4
-----------------------------------------------------
ID1 1 AAA_1 BBB_1
ID1 2 CCC_1 DDD_1
ID2 1 EEE_1 FFF_1
ID2 2 GGG_1 HHH_1
I want to export(overwrite) Table_B column3 data to Table_A column3 , where ID and Number Columns data are equal .
After executing of script , Table_A's data should be ,
Table_A
--------
ID(p_key) Number(p_key) Column3 Column4
-----------------------------------------------------
ID1 1 AAA_1 BBB
ID1 2 CCC_1 DDD
ID2 1 EEE_1 FFF
ID2 2 GGG_1 HHH
How can I make this using sql script only ?
I use MS SQL-Server 2008 R2 .
UPDATE TBLA
SET TBLA.Column3=TBLB.Column3 --, TBLA.Column4=TBLB.Column4 if you want
FROM
Table_A AS TBLA
LEFT OUTER JOIN Table_B AS TBLB ON (TBLB.ID1 = TBLA.ID1 AND TBLB.ID2 = TBLA.ID2)
Please note that 'ID' columns (i.e. 'primary keys') must be unique (as pkeys are :).But to be sure -as I don't know your exact table structure- before you execute the code above, create a SELECT statement with the join(s) and if the result set is correct, then add it to the UPDATE.