delete from 3 tables with one query - sql

i have 3 tables and i dont want define any foreign key in my tables.
my tables structure are like below:
tables diagram
i have written this query :
delete relativedata, crawls, stored
from relativedata inner join
crawls
on relativedata.crawl_id = crawls.id and
relativedata.id = ? inner join
stored
on stored.crawl_id = crawls.id
this query works for me unless one of tables has no records.
now how can i do this delete in 3 tables in 1 query?

If it works if all tables have records, try using LEFT JOIN instread of INNER JOIN. Also, You had some mess with Your joins ON conditions. Try it like this:
delete
relativedata, crawls, stored
from
relativedata
LEFT join crawls on relativedata.crawl_id = crawls.id
LEFT join stored on relativedata.crawl_id = stored.crawl_id
WHERE
relativedata.id = ?
Also, foregin keys are good thing, and not using them is generally bad idea. Yes, they seems to be annoying at first, but try to focus on WHEN they annoy You. Most of the times they do it when You are meddling with data in a way You should not, and without them You wloud cause data incostincency in Your DB.
But, it is just my opinion.

Related

Best way to "SELECT *" from multiple tabs in sql without duplicate?

I am trying to retrieve every data stored in 2 tabs from my database through a SELECT statement.
The problem is there are a lot of columns in each tab and manually selecting each column would be a pain in the ass.
So naturally I thought about using a join :
select * from equipment
join data
on equipment.id = data.equipmentId
The problem is I am getting the equipment ID 2 times in the result.
I thought that maybe some specific join could help me filter out the duplicate key, but I can't manage to find a way...
Is there any way to filter out the foreign key or is there a better way to do the whole thing (I would rather not have to post process the data to manually remove those duplicate columns)?
You can use USING clause.
"The USING clause specifies which columns to test for equality when
two tables are joined. It can be used instead of an ON clause in the
JOIN operations that have an explicit join clause."
select *
from test
join test2 using(id)
Here is a demo
You can also use NATURAL JOIN
select *
from test
natural join test2;

How to optimize the Conditional select query that involve inner joins in it?

I have got an sql query that has lots of INNER JOINS between other tables.
I know that we can use Joins to optimize but as we can see, this query already involved Joins in it. I was thinking to add GROUP BY to this statement which gets more realistic and could run better. Do selecting more columns from one to other tables cause the query slow? If so, how could it work if we need to optimize? Below is my code:
SELECT /*PARALLEL(4)*/
s.task_seq_num,
s.group_seq_num AS grp_seq_num,
g.source_type_cd,
d.doc_id,
d.doc_ref_id AS doc_ref_id,
dm.doc_priority_num AS doc_priority,
s.doc_seq_num AS doc_seq_num,
s.case_num AS case_num,
dm.doc_title_name AS doc_title,
s.task_status_cd AS task_status_cd,
d.received_dt AS received_dt,
nvl(b.first_name,d.first_name) AS first_name,
nvl(b.mid_name,d.mid_name) AS mid_name,
nvl(b.last_name,d.last_name) AS last_name,
tg.content_tag_cd AS content_tag_cd,
d.app_num AS app_num,
e.head_of_household_sw AS head_of_household_sw,
f.user_id AS user_id
FROM
dm_task_status s
INNER JOIN dm_task_tag tg ON s.task_seq_num = tg.task_seq_num
INNER JOIN dm_doc_group g ON g.group_seq_num = s.group_seq_num
INNER JOIN dm_doc d ON d.doc_seq_num = s.doc_seq_num
INNER JOIN dm_doc_master dm ON dm.doc_ref_id = d.doc_ref_id
LEFT JOIN mo_employees f ON f.emp_id = s.emp_id
LEFT JOIN ( dc_case_individual e
INNER JOIN dc_indv b ON b.indv_id = e.indv_id
AND e.head_of_household_sw = 'Y' ) ON e.case_num = s.case_num
WHERE
s.office_num =38
AND s.eff_end_tms IS NULL
AND d.delete_sw IS NULL
ORDER BY s.group_seq_num ASC;
Any ideas are appreciated
First,
AND d.delete_sw IS NULL
should be up in the join and not in the WHERE clause. I don't THINK that matters for performance, but don't trust me on that one. But I do know that it's just good policy to only have the final WHERE clause constructed of the primary table itself.
Second, Since we don't know the data itself or the structure of the data, I would say on EACH join, ensure that you're using a table index wherever possible to prevent full table scans. It seems like something that might be insulting to suggest, but I've made the mistake in the past many times without realizing that there was in fact a place where I was NOT using an indexed field to limit the data scanned.
For example, are all of the fields I list below a part of the primary key of their respective tables? If so, are they the FULL primary key? If they are not the full primary key, is there any way that you can get the rest of the primary key values from the table(s) that you're "coming from"? SQL will try to do the best job it can to make the most efficient plan, but it can only go so far, we always have to try to ensure we're using indexed fields and preferably primary keys to ensure that the database doesn't have to work harder than it has to.
Fields in question:
dm_task_tag.task_seq_num
dm_doc_group.group_seq_num
dm_doc.doc_seq_num
dm_doc_master.dm.doc_ref_id
mo_employees.emp_id
dc_case_individual.indv_id
dc_case_individual.case_num
I'm VERY suspicious of that second LEFT join, but I can't state much about that without knowing the tables. I'm also especially curious if the doc_ref_id is in fact the primary key of the dm_doc_master, or if you have a seq_num that you're missing...

SQL query to output data from two tables that are not directly linked by PK/FK, but are linked through multiple other tables?

I am new to SQL and DBMS' and so I am still learning best practices and exploring what is possible and not possible. I have designed a database in Postgres, which contains 6 tables: SATELLITE DATA which has a Foreign Key with CROP DATA which has a FK with FIELDS which has a FK with FARMS which has a foreign key with MET STATION and MET DATA which also has a foreign key with MET STATION. (I hope I've explained that ok..)
I was assuming that I could get an output table containing information from the 2 tables furthest from each other (SATELLITE DATA and MET DATA) because there was a link through all the other tables via PKs and FKs.. however I can't work out the SQL to do so. (I can envisage a very long bit of SQL to do it.. but if it is possible I would hope there is a more efficient way..)
My questions are: Is there SQL to do what I want above in an efficient manner with the same design of database I've done? Or should I redesign my database so that each table that needs to be linked, is linked directly rather than through multiple other tables?
Thanks in advance for any help!
select *
from one t1
join six t6 ON exists (
select *
from two t2
join three t3 on t3.two_id = t2.two_id
join four t4 on t4.three_id = t3.three_id
join five t5 on t5.five_id = t4.five_id
where t2.one_id = t1.one_id
and t5.six_id = t6.six_id
);
Now you only need to replace the table/column-names by the actual names (that you didn't provide)
The query is not hard. It looks something like this:
select . . .
from met_station ms join
farms f
on ms.farm_id =f.farm_id join
fields fi
on f.field_id = fi.field_id join
crops c
on c.crop_id = f.crop_id join
satellites s
on s.satellite_id = c.satellite_id;
If I understand the data model correctly, these are all 1-n relationships and there is no issue handling the joins. You just have to list them. And, assuming the join keys are primary keys (in one table), performance should be fine.
You do have a challenge when some of the tables are n-m. Handling multiple such relationships often involves aggregating before joining.

SQL - inner join before left join

I have come across some sql that has an inner join right before a left join.
From Table t
INNER JOIN vw_User i ON t.UserID = i.UserID
LEFT JOIN UserTypeTwo it ON t.UserTypeTwoID = it.UserTypeTwoID
Can someone please help me visualize how this works. I can visualize the two joins separately, but since they are one after the other, how do they work together?
See the following image, don't have enough rep to embed it.
http://i.imgur.com/pdMaz56.png
IMO, no better way to express joins than like this:
What will happens is that you are just appending more columns to Table T.
Basically what happens is that Table T has no relationship to UserTypeTwo, but it does to vw_user. Then you need some data from UserTypeTwo but since Table T can't join to userTypeTwo you need a table to connect them both, which is where vw_user comes in which should have a relation to UserTypeTwo.
Basically this query is being used because you need columns from Table T and UserTypeTwo(and probably vw_User as well) so you need to join all three of them.
Table T has FK for vw_User
vw_User has FK to UserTypeTwo
UserTypeTwo has column that you need
(it doesnt necessarily need to be a foreign key but I'm assuming you know this since you have join knowledge).
I hope I was able to clarify what is happening.

SQL Server, fetching data from multiple joined tables. Why is slow?

I have problem with performance when retrieving data from SQL Server.
My sql query looks something like this:
SELECT
table_1.id,
table_1.value,
table_2.id,
table_2.value,...,
table_20.id,
table_20.value
From table_1
INNER JOIN table_2
ON table_1.id = table_2.table_1_id
INNER JOIN table_3
ON table_2.id = table_3.table_2_id...
WHERE table_1.row_number BETWEEN 1 AND 20
So, I am fetching 20 results.
This query takes about 5 seconds to execute.
When I select only table_1.id, it returns results instantly.
Because of that, I guess that problem is not in JOINs, it is in retrieving data from multiple tables.
Any suggestions how I would speed up this query?
Assuming your tables are designed properly (have a useful primary key etc.), then the first thing I would check is this:
are there indices on each of the foreign key columns in the child tables?
SQL Server does not automatically create indices on the foreign key columns - yet those are indeed very helpful for speeding up your JOINs.
Other than that: just look at the query plans! They should tell you everything about this query - what indices are being used (or not), what operations are being executed to get the results....
Without knowing a lot more about your tables, their structure and the data they contain (how much? What kind of values? etc.), there's really not much we can do to help here....
Between can really slow a query, what do you want to achieve with it
also
Do you have an on the columns you are joining on
You could use with(nolock) on the table
Check to execution plan to see whats taking so long
How about this one:
SELECT
table_1.id,
table_1.value,
table_2.id,
table_2.value,...,
table_20.id,
table_20.value
FROM
table_1
INNER JOIN table_2 ON table_1.id = table_2.id AND table_1.row_Number between 1 and 20
INNER JOIN table_3 ON table_2.id = table_3.id
I mean before joining to another table, you choose range of data.