SQL query based on values from another tables - sql

I need to put external courses to "ext" folder.
Which course is external? -External course is course whose vendor doesn't have a client_id.
So first we check if vendor for our course has a client_id, we will check for that in vendor table. If our vendor doesn't have client_id (client_id = NULL) then we want to grab an ID of "ext" record from folder table and insert it to folder_id column. If our vendor has a client_id we dont do anything, so second row in course table under folder_id will be empty. Folder_id column should be populated like this: 1.row = 2, 2.row = (empty), 3.row = 2, 4.row = 2, 5.row = 2.
Here is the code that I have for now but I'm getting 'column reference "id" is ambiguous' at line 2. I dont know if code is good, I'm not that good with sql.
(prefix 't' in code means table)
UPDATE t_course SET folder_id = (SELECT id FROM t_folder WHERE code IS NULL)
WHERE id IN (SELECT id
FROM t_course course
JOIN t_vendor vendor ON vendor.id = course.vendor_id
WHERE vendor.client_id IS NULL);

I suspect you really want EXISTS:
UPDATE t_course c
SET folder_id = (SELECT f.id FROM t_folder f WHERE f.code IS NULL)
WHERE EXISTS (SELECT 1
FROM t_vendor vendor
WHERE v.id = c.vendor_id AND v.client_id IS NULL
);

Related

Select rows having value combination listed in another table

I have tables:
Result containing 5 columns: result_id, num_1, num_2, num_3, num_4
Ref containing 4 columns: num_1, num_2, num_3, num_4
Columns num contain random int in range of 1-9
Aim of exercise is to display all result_id from Result table which have num values combination present in Ref table and to display result_id which have not met combination criteria.
I've been trying left joining ref to result, but unfortunately no success. Could you please share some light how to deal with it?
If you want the result_id for which combination exists in the ref table then use following JOIN query:
select distinct r.result_id
from results r
join ref on r.num_1 = ref.num_1 and r.num_2 = ref.num_2
and r.num_3 = ref.num_3 and r.num_4 = ref.num_4
If you want the result_id for which combination do not exists in REF table then use the LEFT JOIN as follows:
select r.result_id
from results r
left join ref on r.num_1 = ref.num_1 and r.num_2 = ref.num_2
and r.num_3 = ref.num_3 and r.num_4 = ref.num_4
where ref.num_1 is null -- or use PK / Not nullable column of REF table here
Assuming you want the columns to "line up" and you want to add a flag to the result_id in the first table, then use exists:
select t1.*,
(case when exists (select 1
from table2 t2
where t2.n1 = t1.n1 and t2.n2 = t1.n2 and t2.n3 = t1.n3 and t2.n4
)
then 'present' else 'not present'
end) as flag
from t2;

Create recursive query where column values need to get based on another column | ORACLE

I have two tables where one table has list of issues and another table has its parent issue in form of issue id.
I am only mentioning required columns
1st table
ID, ISSUENUM, PROJECTKEY
2nd Table
JSON_VALUE has parent_id which is ID from 1st table
END result expectation
ID, ISSUENUM, PROJECT KEY, PARENT_ISSUENUM, PARENT_PROJECT_KEY
I have query till this point, but unable to make hierarchical/ recursive query
(select json_value(EP.JSON_VALUE, '$.parent_id' RETURNING NUMBER)as xyz
from JIR.ENTITY_PROPERTY EP where EP.ENTITY_ID = JI.ID AND EP.ENTITY_NAME = 'IssueProperty'
AND json_exists(EP.JSON_VALUE, '$.parent_id'))as parent_id
from jir.project p,jir.jiraissue JI
where p.id = ji.project
and (p.pkey = 'ABCDEF' OR p.pkey = 'UVWXYZ')
How to use this ID which I have as column parent_id and use it to get parent_issue_num and parent_project_key
I solved it myself. I improved the query on getting parent_id and get parent_key using column query itself
select JI.ID,
(select P.PKEY||'-'||ji2.issuenum
from JIR.ENTITY_PROPERTY EP
inner join jir.jiraissue JI2 on ji2.id=json_value(EP.JSON_VALUE, '$.parent_id' RETURNING NUMBER)
inner join jir.project p2 on p2.id=ji2.project
where EP.ENTITY_ID = JI.ID AND EP.ENTITY_NAME = 'IssueProperty'
AND json_exists(EP.JSON_VALUE, '$.parent_id'))as parent_id
from jir.project p,jir.jiraissue JI
where p.id = ji.project
and (p.pkey = 'ABCDEF' OR p.pkey = 'UVWXYZ')
This small change resolved the issue
inner join jir.jiraissue JI2 on ji2.id=json_value(EP.JSON_VALUE, '$.parent_id' RETURNING NUMBER)
inner join jir.project p2 on p2.id=ji2.project

SQL Delete Where Not In with Composite Key

I have a system integration project which needs to CRUD from one DB to another. Not especially complicated. However, when it comes to deleting rows which exist in the target but not in the source, I ran into a little trouble. The standard patterns include: LEFT JOIN, NOT EXISTS or NOT IN. I chose the LEFT JOIN. My 'Phone' table uses a composite key, Employee 'Id' and the PhoneType: Work, Home, Mobile, etc. The standard left join will delete ANY target Phone number NOT in the source. This clears out the whole table. NOTE: I am updating only records which have changed since the last update, NOT the whole target & source. So, I wrote a fix which I suspect is really poor SQL:
-- SOURCE
DECLARE #tmpPhones TABLE(Id varchar(8), PhoneType int, PhoneNumber varchar(30), PRIMARY KEY (Id, PhoneType))
INSERT into #tmpPhones values
('TEST123', 1, '12345678'),
('TEST123', 2, '12345678'),
('TEST123', 3, '12345678')
-- TARGET
DECLARE#Phone TABLE( Id varchar(8), PhoneType int, PhoneNumber varchar(30), PRIMARY KEY (Id, PhoneType))
INSERT into #Phone values
('TEST123', 1, '12345678'), <-- Exists in both, leave
('TEST123', 2, '12345678'), <-- Exists in both, leave
('TEST123', 3, '12345678'), <-- Exists in both, leave
('TEST123', 4, '12345678'), <-- ONLY delete this one!
('TEST456', 2, '12345678'), <-- Ignore this employee Id
('TEST456', 3, '12345678'), ""
('TEST456', 4, '12345678') ""
DELETE p
FROM #Phone p
LEFT JOIN #tmpPhones t
ON t.Id = p.Id AND t.PhoneType = p.PhoneType
WHERE t.Id IS NULL AND t.PhoneType IS NULL
AND p.Id IN (SELECT Id FROM #tmpPhones) <-- a sad hack?
This works, but I feel like there is a better way to make sure we are only deleting records for THIS employee, not all the others.
Any suggestions?
Use exists.
DELETE p
FROM #Phone p
where exists (select 1 from #tmpPhones where Id = p.Id)
AND not exists (select 1 from #tmpPhones where PhoneType = p.PhoneType)
Edit: Deleting using cte.
with todelete as (
select id,phonetype from phone
except
select id,phonetype from tmpphones t
where exists (select 1 from phone where id = t.id)
)
delete from phone
where exists (select 1 from todelete where phone.id = id and phone.phonetype = phonetype)
I think two exists statements pretty much capture the logic: as you describe it
DELETE p
FROM #Phone p
WHERE EXISTS (SELECT 1 FROM #tmpPhone t WHERE t.id = p.id) AND
NOT EXISTS (SELECT 1 FROM #tmpPhone t WHERE t.id = p.id AND t.PhoneType = p.PhoneType) ;
merge seems to work ok - but you still need to see if the id is in your reference set, I don't see a clean way around that
MERGE #Phone AS TGT
USING (
SELECT * FROM #tmpPhones
) AS SRC
ON TGT.ID=SRC.ID AND TGT.PHONETYPE=SRC.PHONETYPE
WHEN NOT MATCHED BY SOURCE AND tgt.id IN (SELECT id FROM #tmpPhones) THEN DELETE;

Select data from child parent relationship of the same table

I have below table schema:
create table location_master (id serial,name character varying,parent_id integer);
INSERT INTO location_master (name,parent_id)
VALUES
('Bombay',1)
, ('Ahmedabad',1)
, ('Surat',1)
, ('Vapi',3)
, ('Navarangpura',2);
From above table I want to find the path from source id = 1 to destination id = 4. So the expected result is as below:
Here destination id = 4. Which has parent_id = 3. On words id = 3 has parent_id = 1 and so on.
Example:
A user wants to send a parcel from id = 1 to id = 4. Routing path for the parcel is decided by this table. When a user selects source id = 1 and destination id = 4 then the query automatically finds the route from child-parent relationship. Parcel will go through 1,3,4 path.
I tried SELF JOIN for this but did not get the expected result.
Thanks joop. I search for Recursive Query and got the solution as I want:
WITH RECURSIVE demo AS (
SELECT parent_id
FROM location_master
WHERE id = <destination_id>
UNION ALL
SELECT a.parent_id
FROM location_master a
JOIN demo b ON(a.id = b.parent_id))
SELECT DISTINCT location_master.* FROM location_master JOIN demo
on location_master.id = demo.parent_id WHERE demo.parent_id != 0
UNION
SELECT location_master.* FROM location_master WHERE id = <destination_id>
ORDER BY id ;

Selective update in SQL Server

I've created a junction table like this one:
http://imageshack.us/scaled/landing/822/kantotype.png
I was trying to figure out a query that could able to select some rows - based on the PokémonID - and then updating only the first or second row after the major "filtering".
For example:
Let's suppose that I would like to change the value of the TypeID from the second row containing PokémonID = 2. I cannot simply use UPDATE KantoType SET TypeID = x WHERE PokémonID = 2, because it will change both rows!
I've already tried to use subqueries containing IN,EXISTS and LIMIT, but with no success.
Its unclear what are your trying to do. However, you can UPDATE with JOIN like so:
UPDATE
SET k1.TypeID = 'somethng' -- or some value from k2
FROM KantoType k1
INNER JOIN
(
Some filtering and selecting
) k2 ON k1.PokémonID = k2.PokémonID
WHERE k1.PokémonID = 2;
Or: if you want to UPDATE only the two rows that have PokémonID = 2 you can do this:
WITH CTE
AS
(
SELECT *,
ROW_NUMBER() OVER(ORDER BY TypeID) rownum
FROM KantoType
WHERE PokemonID = 2
)
UPDATE c
SET c.TypeID = 5
FROM CTE c
WHERE c.rownum = 1;
SQL Fiddle Demo
I can suggest something like this if you just need to update a single line in your table:
UPDATE kantotype
SET
type = 2
WHERE pokemon = 2
AND NOT EXISTS (SELECT * FROM kantotype k2
WHERE kantotype.type > k2.type
AND kantotype.pokemon = k2.pokemon)
It would be easier to get the first or last item of the table if you had unique identifier field in your table.
Not sure even if you are trying to update the row with PokemenID =2 by doing a major filtering on TypeID... So just out of assumptiong (big one), you can give a try on Case
UPDATE yourtable a
LEFT JOIN youtable b on a.pokeid = b.pokeid
SET a.typeid = (CASE
WHEN a.typeid < b.typeid THEN yourupdatevalue
WHEN a.typeid > b.typeid THEN someothervalue
ELSE a.typeid END);
If you know the pokemon ID and the type id then just add both to the where clause of your query.
UPDATE KantoType
SET TypeID = x
WHERE PokémonID = 2
AND TypeID=1
If you don't know the type ID, then you need to provide more information about what you're trying to accomplish. It's not clear why you don't have this information.
Perhaps think about what is the unique identifier in your data set.