t-sql update issue - sql

tbl_indicator
grp_nbr, sect_nbr, indicat
001234 100 p
002345 101 s
tbl_group
grp_id, grp_nbr, sect_nbr, indicat
333 001987 100 a
555 001987 100 p
444 002987 101 s
222 02987 101 y
Here (in tbl_group) grp_id is the primary Key
tbl_order
order_id, grp_id
5000 333
5001 555
5002 555
5003 555
5004 444
5005 444
5006 222
In tbl_order, grp_id is a foreign Key to grp_id in tbl_group.
In table tbl_indicator, for one set of grp_nbr and sect_nbr there is an indicat, for the same set of grp_nbr and sect_nbr there is a correct indicat (555,1, 100, p) and a junk indicat (333, 1, 100, a) in table tbl_group, but both these grp_id (333, 555) are present in table tbl_orders.
And one more thing here is that the junk data (indicat) in group table (222, 02987, 101, y) the grp_nbr has one character length less than the grp_nbr in tbl_indicat. It should use something 'LIKE' operator
How can we handle this??
Now I need to update tbl_order table in such a way that the junk grp_id s should be replaced with correct grp_id s
The output should like:
tbl_orders
order_id, grp_id
5000 555
5001 555
5002 555
5003 555
5004 444
5005 444
5006 444
I already have answer if both the column data in tbl_indicat and tbl_grp tables are same...
It was answered by 'Dr. Wily's Apprentice'
sql update (help me )
but how to handle if the data is different (like missing some strings in starting)?

UPDATE o
SET o.grp_id = g2.grp_id
FROM tbl_order AS o
INNER JOIN tbl_group AS g1
ON g1.grp_id = o.grp_id
INNER JOIN tbl_group AS g2
ON g2.sect_nbr = g1.sect_nbr
AND g2.grp_nbr = '0' + g1.grp_nbr

Related

Joining table twice with output based n new table

I am having trouble joining a table twice on the same column.
Table People
name
phone_number
Pamela
113 555 7544
Jordan
328 555 9658
Haley
502 555 6712
Table Phone_calls
caller
receiver
duration
113 555 7544
328 555 9658
234
328 555 9658
502 555 6712
500
502 555 6712
113 555 7544
468
Desired output
duration
caller_name
receiver_name
234
Pamela
Jordan
SELECT name as caller_name, name as receiver_name, duration
FROM people
JOIN phone_calls ON people.phone_number=phone_calls.caller
JOIN phone_calls ON people.phone_number=phone_calls.receiver
ORDER BY duration;
How should differentiate the two name links I want to output?
This is where aliases make for an easier query:
select pc.duration, c.Name as Caller_name, r.Name as Receiver_name
from Phone_calls pc
join People c on c.phone_number = pc.caller
join People r on r.phone_number = pc.receiver
order by pc.duration;
I'm not sure if I understood your question correctly but, assuming the desired output you've mentioned is indeed the output you desire, this query correctly returns your output:
create table people (
nome varchar(50) primary key,
phone_number varchar(50)
);
insert into people values ('Pamela', '113 555 7544');
insert into people values ('Jordan', '328 555 9658');
insert into people values ('Haley', '502 555 6712');
select * from people;
create table phone_calls (
caller varchar(50),
receiver varchar(50),
durations int
);
insert into phone_calls values ('113 555 7544', '328 555 9658', 234);
insert into phone_calls values ('328 555 9658', '502 555 6712', 500);
insert into phone_calls values ('502 555 6712', '113 555 7544', 468);
select
tt.durations,
tt.caller_name,
p.nome as "receiver_name"
from
(
select
pc.durations,
p.nome as caller_name,
pc.receiver as telefone
from people p
left join phone_calls pc
on p.phone_number = pc.caller
) tt
left join people p
on tt.telefone = p.phone_number
where tt.caller_name = 'Pamela';

Netezza SQL Join dataset A to dataset B but pull fields from B when b_date > a_date

I have 2 datasets from 2 different sources but many of the members are the same in both datasets. My select statement is :
Select a.member_id, a.start_date, a.customer_id, a.region_id, b.b_start_date, b.customer_id, b.region_id
from dataset1 a
left join dataset2 b
on a.member_id=b.member_id
I want to somehow pick up all recs in A and recs in B where a.member_id = b.member_id but bring in the fields from A when a.start_date = b.b_start_date or a.start_date > b.b_start_date and bring in the fields from B when b.b_start_date > a.start_date.
Here's a pretty small example:
Dataset A:
member_id
start_date
customer_id
region_id
1111
1/30/2021
123
555
2222
1/30/2021
222
555
3333
1/1/2021
345
678
Dataset B:
member_id
b_start_date
customer_id
region_id
1111
1/1/2022
567
444
2222
1/30/2021
222
555
Result:
member_id
customer_id
region_id
1111
567
444
2222
222
555
3333
345
678
/* try this */
select a.* from a inner join b using (member_id) where a.start_date >= b.b_start_date
union all
select b.* from a inner join b using (member_id) where b.b_start_date > a.start_date;

Oracle get latest value based on parent/child partition

I have a table named "customer" that looks like this:
ID ALPHA BRAVO CHARLIE DATE
-------------------------------------------------
1 111 222 333 02/02/2019
2 333 444 555 11/11/2019
3 666 555 777 12/12/2019
4 777 888 999 05/05/2020
5 100 101 110 12/25/2020
and I need to get the following output:
ID ALPHA BRAVO CHARLIE DATE NEW_COL ROW_NUM
-----------------------------------------------------------------------
1 111 222 333 02/02/2019 333 4
2 333 444 555 11/11/2019 333 3
3 666 555 777 12/12/2019 333 2
4 777 888 999 05/05/2020 333 1
5 100 101 110 12/25/2020 010 1
The ALPHA, BRAVO, and CHARLIE columns represent customer IDs. A given customer can have multiple IDs in the system. Records 1-4 represent IDs belonging to the same customer, let's say John. As per the table, John has 12 IDs, and his latest ID is 999. Record 5 represents another customer, let's say Jane. Jane has three IDs, and her last ID is 110.
The purpose of the ROW_NUM column is to get the last CUSTOMER.CHARLIE value. The idea is to use the first CHARLIE value as the partition. Basically, the goal is to get one parent:many children mapping. In this case, the ID 333 should be tied to 555, 777, and 999.
Here is the DDL/DML:
CREATE TABLE CUSTOMER
(ID NUMBER(20) NOT NULL,
ALPHA NUMBER(20) NOT NULL,
BRAVO NUMBER(20) NOT NULL,
CHARLIE NUMBER(20) NOT NULL,
CREATEDDATE DATE
);
INSERT INTO CUSTOMER
VALUES
(1, 111, 222, 333, to_date('02-FEB-19','DD-MON-RR'));
INSERT INTO CUSTOMER
VALUES
(2, 333, 444, 555, to_date('11-NOV-19','DD-MON-RR'));
INSERT INTO CUSTOMER
VALUES
(3, 666, 555, 777, to_date('12-DEC-19','DD-MON-RR'));
INSERT INTO CUSTOMER
VALUES
(4, 777, 888, 999, to_date('05-MAY-20','DD-MON-RR'));
INSERT INTO CUSTOMER
VALUES
(5, 100, 101, 110, to_date('25-DEC-20','DD-MON-RR'));
COMMIT;
I have tried the following query, but it fails to populate the partition column correctly:
WITH
charlies
AS
(SELECT DISTINCT charlie
FROM customer),
mult_customers
AS
(SELECT c.*, c.charlie AS NEW_COL
FROM customer c
UNION
SELECT c.*,
CASE WHEN c.alpha = e.charlie THEN c.alpha ELSE c.bravo END AS NEW_COL
FROM customer c
JOIN charlies e ON e.charlie = c.alpha OR e.charlie = c.bravo),
ranked
AS
(SELECT mc.*,
ROW_NUMBER ()
OVER (PARTITION BY NEW_COL ORDER BY createddate DESC) AS row_num
FROM mult_customers mc)
SELECT *
FROM ranked
ORDER BY ID;
Thanks for any help provided.
You task is known as connected components. I wrote about 7-8 years ago solution for this and even pl/sql package: http://orasql.org/2017/09/29/connected-components/
This PL/SQL solution is much more effective then pure SQL solutions: http://orasql.org/2014/02/28/straight-sql-vs-sql-and-plsql/
Let me know if you need help with adopting it for your task.

finding manager id from employee table

I have a table data like in the below.
Emp_id Emp_name Dept_id
111 aaa 1
222 bbb 2
333 ccc 3
444 ddd 4
555 eee 5
Then i want to populate new column manager id as next emp_id from the employee table like in the below.
Emp_id Emp_name Dept_id Manager_id
111 aaa 1 222
222 bbb 2 333
333 ccc 3 444
444 ddd 4 555
555 eee 5 111
Thanks for your help in advance!
You can return the value as:
select t.*,
coalesce(lead(empid) over (order by empid),
min(empid) over ()
) as manager_id
from t;
Perhaps a select query is sufficient. Actually modifying the table is a bit tricky and the best syntax depends on the database.

SQL to fetch least 2 salaries from a table department wise

How would be the SQL to fetch least 2 salaries from a table department wise ?
Sample Table:
empid salary Dept
---------------------
101 2000 aaa
102 1000 bbb
103 5000 bbb
104 8000 ccc
105 3000 aaa
106 4000 aaa
107 6000 ccc
108 7000 bbb
109 9000 ccc
Output should be like:
Dept empid salary
----------------------
aaa 101 2000
aaa 105 3000
bbb 102 1000
bbb 103 5000
ccc 104 6000
ccc 107 8000
SELECT
t.dept
,t.empid
,t.salary
FROM
#test t
WHERE
t.empid IN (
SELECT TOP 2
empid
FROM
#test
WHERE
dept = t.dept
ORDER BY
salary
)
ORDER BY
dept,empid
As was pointed out, there may be other people in dept ccc with a salary of 8000 that will be missed.
Following this blog post and supposing the table name is "samptab":
select dept, empid, salary
from samptab
where (
select count(*) from samptab as s
where s.dept = samptab.dept and s.salary <= samptab.salary
) <= 2 order by dept;
You can change the number "2" in the query row if you want more or less rows.