I have three tables. One is a table of deletion candidates. This table was created with certain criteria, but did not include a couple of factors for consideration (limitations of the system). The other two tables were created considering those "left out" factors. So, I need to run a SELECT query on these three tables to come up with a deletion list.
What I started with is:
SELECT inactive.id
FROM inactive, renamed, returned
WHERE NOT EXISTS (inactive.id = remamed.id and inactive.id = returned.id)
But this is giving me an error. Can someone point out my error here?
Thank you
It's not entirely clear what you are trying to do here.
I assume you want a list of all rows from the inactive table that do not exist in either the renamed table or the inactive table. Is that right?
If so you can use a query like this:
SELECT inactive.id
FROM inactive
WHERE NOT EXISTS (select null from renamed where renamed.id = inactive.id)
AND NOT EXISTS (select null from returned where returned.id = inactive.id)
Related
I am using MySQL for the following: I have 2 tables, sw_products and sw_components. Each sw_product can be made up of multiple sw_components. And there is another relation table where each row specifies the product and a component it is uses.
Each sw_component has a status: 'ready', 'not-ready', and 'unusable'. And each sw_product also has a status which corresponds to the lowest status of all of its components.
What I was doing was trying was to create a TRIGGER UPDATE when sw_components updates, but then I'd need to cycle through all the sw_products that use that sw_component and change their status if the new status is higher. How can I do this inside a trigger? (assign a variable to a select statement, and cycle through each row, maybe?)
Thanks!
I´m the OP. I was able to solve the problem after some thinking. As Ultimater said, you can use cursors, but they´re read only, so you can go into some trouble, and I thought they were over-complicated (but still, thanks!).
What I did was changed the status from VARCHARS to INTEGERS, then I created a View of each product alongside their lowest status (using a MIN(status):
CREATE VIEW product_status_by_component AS
SELECT s_name, s_version, min(status) AS min
FROM sw_components
JOIN sw_build
ON sw_components.name = c_name AND sw_components.version = c_version
GROUP BY s_name, s_version;
Then I used a trigger each time a components status got updated. I found out you Update unrelated tables even if the trigger does not belong to them, and that you could join tables inside an update:
UPDATE sw_products a
LEFT JOIN product_status_by_component b ON
a.name = b.s_name AND a.version = b.s_version
SET
a.status = b.min;
I had an issue joining multiple tables to retrieve the data I needed. In order to accomplish the proper results I had to first create a view (shown below) called: vwinvgrossrev :
SELECT dbo.inv_item.inv_num, dbo.inv_item.co_line,
dbo.inv_hdr.co_num, dbo.inv_hdr.inv_date, dbo.inv_item.qty_invoiced,
dbo.inv_item.price
FROM dbo.inv_item INNER JOIN
dbo.inv_hdr ON dbo.inv_item.inv_num = dbo.inv_hdr.inv_num
and then I had to join the view on my final table in order to create a proper summation of the values that I wanted
select sum(vwinvgrossrev.qty_invoiced*vwinvgrossrev.price)
from vwinvgrossrev,coitem
WHERE vwinvgrossrev.co_num=coitem.co_num
AND coitem.Uf_Erne='Y'
AND vwinvgrossrev.co_line=coitem.co_line
AND DATEPART(mm,vwinvgrossrev.inv_date) = DATEPART(mm,Getdate())
AND YEAR(vwinvgrossrev.inv_date) = YEAR(Getdate())
My question is this. Is there anyway to do this in a single query. The problem is all 3 tables have a many to many relationship with one another and always returns the wrong value when joining all 3 tables.
If your current query (using the view) gives you what you are looking for then I believe that this query will give you the same thing in a single query:
SELECT sum(inv_item.qty_invoiced*inv_item.price)
FROM inv_item
JOIN inv_hdr ON dbo.inv_item.inv_num = dbo.inv_hdr.inv_num
JOIN coitem ON (inv_hdr.co_num=coitem.co_num
AND inv_item.co_line=coitem.co_line)
WHERE coitem.Uf_Erne='Y'
AND vwinvgrossrev.co_line=coitem.co_line
AND DATEPART(mm,inv_hdr.inv_date) = DATEPART(mm,Getdate())
AND YEAR(inv_hdr.inv_date) = YEAR(Getdate())
However, I'll be surprised if that is what you are looking for.
I am assuming that you don't actually have a many-to-many between all 3. I am assuming that inv_hdr has a unique inv_num and inv_item has many of those. Similarly I am assuming that co_num is unique within inv_hdr but has multiple occurrences within coitem. These are not many-to-many but rather 1-to-many relationships. Since SELECT multiplies rows I think you are going to be summing way more than you want.
Why do you want to include coitem at all if you are just interested in inv_item.qty_invoiced and inv_item.price? Is it just to limit on the Uf_Erne column? Is coitem always going to have either 1 or 0 records for that co_num and co_line with Uf_Erne='Y'?
In sum, I've reproduced your query in a single query without a view, but I think you may need to think through whether this is really what you want.
You need to refine your database schema to normalise out the many-to-many relationships. That is a given and is standard practice regardless of your current problem. The fact that it will simplify your current problem is the reason why. There are many tutorials/blog/etc out there to show you how to do this with join tables so I am not going into it here.
This is a theoretical scenario, and I am more than amateur when it comes to large scale SQL databases...
How would I go about inserting around 2million records into an existing database off 6million records (table1 into table2), whilst at the same time using email de-duplication (some subscribers may already exist in site2, but we don't want to insert those that already exist)?
I understand how to simply get the records from site 1 and add them into site 2, but how would we do this on such a large scale, and not causing data duplication? Any reading sources would be more than helpful for me, as ive found that a struggle.
i.e.:
Table 1: site1Subscribers
site1Subscribers(subID, subName, subEmail, subDob, subRegDate, subEmailListNum, subThirdParties)
Table 2: site2Subscribers
site2Subscribers(subID, subName, subEmail, subDob, subRegDate, subEmailListNum, subThirdParties)
I would try something like this:
insert into site2Subscribers
select * from site1Subscribers s1
left outer join site2Subscribers s2
on s1.subEmail = s2.subEmail
where s2.subEmail is null;
The left outer join along with the null check will return only those rows from site1Subscribers that have no matching entry in site2Subscribers.
I have a dynamic amount of tables with the same column structure. I wish to update certain rows in all of them with a single query. Any multi-table UPDATE examples I've found have to do with doing different columns in different tables, and updating one table based on the value in another table. My issue is that I have the same column in all tables, and it is a dynamic number of tables.
As an example of this, I would have table_a, table_b, and table_c. All three tables would share the same structure: id and status.
I want to update the status column in all three at once to a known value.
This is the queries that I would like to essentially combine in this example.
UPDATE table_a SET status = 'closed' WHERE id = 5
UPDATE table_b SET status = 'closed' WHERE id = 5
UPDATE table_c SET status = 'closed' WHERE id = 5
Since the amount of tables is dynamic, I feel this would be cleanest with a single query. I have an array of the table names in PHP (loaded dynamically for this system) and can iterate them to form joins or concatenate a string if needed.
Here is an example of what I thought would work.
UPDATE table_a, table_b, table_c
SET status = 'closed'
WHERE id = 5
The problem with this query is that I get an error about ambiguity for the column names.
Do I need to make it like something this?
UPDATE table_a, table_b, table_c
SET table_a.status = 'closed', table_b.status = 'closed', table_c.status = 'closed
WHERE table_a.id = 5 OR table_b.id = 5 OR table_c.id = 5
I'm assuming this would work and might not be too bad, as the expected amount of tables really ranges from 1-10 maybe. However, I was really hoping for a more efficient way. Firing off individual queries might not be so bad with that few of queries, but in a big system every bit of optimization counts!
Thank you for any help.
Please note that the structure of having multiple tables with the same scheme is by design, as it is a tracker system that separates multiple locations. The example only reflects the basic structure of the idea I need to implement; the real thing is much more complicated. Also, stored procedures will not be an option in this project.
Yes, you'll need to qualify each table / column that you want to update if they use the same logical names.
The query sees you're looking for a logical name of 'status', but you've defined 'status' to be the logical name for 3 different physical locations in the database. Which one did you mean? There are many things that can be done when multiple tables are involved. So for a database to assume you want to update all of them would be very bad.
Title might be confusing, didn't quite know how to put it. Here's what i need to do. I have two tables, cronjobs and cronjob_seeds. I need to see if a cronjob exists before adding it to the database.
Consider these tables:
cronjobs:
-id- -callback_model- -callback_method-
1 movie_suggestion_model fetch_similar_movies
cronjob_seeds:
-cronjob_id- -seed-
1 seed1
1 seed2
Before adding a new cronjob, i need to see if the exact same cronjob exists in the database. I wrote the following query, but it doesn't work if the cronjob has multiple seeds. It works good if it only has one seed, but every time a cronjob has multiple seeds it returns nothing.
SELECT `id`
FROM (`cronjobs`)
INNER JOIN `cronjob_seeds` ON `cronjob_seeds`.`cronjob_id` = `cronjobs`.`id`
WHERE `cronjobs`.`callback_model` = 'movie_suggestion_model'
AND `cronjobs`.`callback_method` = 'fetch_similar_movies'
AND `cronjob_seeds`.`seed` = '1'
AND `cronjob_seeds`.`seed` = 10
Am i missing something? Should i be using another type of join?
And, off topic, but a seed is a parameter for the callback method, i just named it a little weird.
You should use IN clause
Change your query to:
SELECT `id`
FROM (`cronjobs`)
INNER JOIN `cronjob_seeds` ON `cronjob_seeds`.`cronjob_id` = `cronjobs`.`id`
WHERE `cronjobs`.`callback_model` = 'movie_suggestion_model'
AND `cronjobs`.`callback_method` = 'fetch_similar_movies'
AND `cronjob_seeds`.`seed` IN ('seed1', 'seed2')
Only to check if a cron entry exists, you don't need a join, unless you need to check if it exists and has specific seeds. To check only if a cron entry exists you need to do something like this:
SELECT `id`
FROM `cronjobs`
WHERE `cronjobs`.`callback_model` = 'movie_suggestion_model'
AND `cronjobs`.`callback_method` = 'fetch_similar_movies'
How come your query return result even when you had a single row for _cronjob_seeds_ . Cause the last two AND criteria conflict with each other. You should revise it as :
AND `cronjob_seeds`.`seed` BETWEEN '1' AND '10'
Also are you questioning the existance of a record in cronjob_seed or in cronjob? Your query parameters does not seem to be clear. Are you trying to check whether a specific cronjob with specific seeds exist? Tip: try to write the query in human language than sql