MYSQL join query advice (removing orphaned rows) - mysql

I have two tables as follows..
campaigns(campaignID, title)
campaignMailList(campaignID, Sent)
(The 2 tables are bigger.. but for this purpose I only need these columns)
I want to do generate a query that will DELETE all rows in campaignMailList where it cannot find a join in the campaigns table on the campaignID.
Can anyone suggest how I do this?

Translating word by word your own question into SQL:
delete from campaingMailList where
campaingId not in (select campaingid from campaigns)

You could try the NOT IN clause.
Like
DELETE FROM `campaignMailList` as cml
WHERE cml.campaignid NOT IN ( SELECT campaignID FROM campaigns )
Not sure if it is the fatest way to do this

Try this query -
DELETE cml FROM campaignMailList cml
LEFT JOIN campaigns c
ON c.campaignID = cml.campaignID
WHERE c.campaignID IS NULL

Related

Query to join 3 tables

I need to write a query to join 3 tables.
My tables are:
ucommerce_customer
ucommerce_order
ucommerce_order_line
All 3 tables have a column called order_id.
The table ucommerce_order has a column called order_status.
When the order_status is set to "open" I want to display the order details.
ResultSet myRs = myStmt.executeQuery
("SELECT * FROM ucommerce_customer
INNER JOIN ucommerce_order
INNER JOIN ucommerce_order_line
WHERE ucommerce_order.order_status = 'open'");
My query ignores the order status and displays all orders, open and closed.
Also I have several products so ucommerce_order_line has several entries for the same order_id, my query displays duplicate entries and it duplicates the entire list as well.
How can I write a query that will show only open orders without duplicating everything?
In MySQL, the on/using clause is optional. This is very sad because someone can make mistakes like you did. Your question only mentions one column, so perhaps that is all that is needed for the join:
SELECT *
FROM ucommerce_customer INNER JOIN
ucommerce_order
USING (orderId) INNER JOIN
ucommerce_order_line
USING (OrderId)
WHERE ucommerce_order.order_status = 'open';
I would be surprised if the customer table really had a column called OrderId (seems like a bad idea in most situations), so the first USING clause might want to use CustomerId.
I would recommend to use a natural join instead. Maybe that's where the errors are coming from.
The duplicates can be removed by running SELECT DISTINCT * ...

MySQL - Records that don't exist in another table - showing incorrect results

This is my first post here.
I'm trying to display records from one table into another where they do not already exist using an outer join.
SELECT a.fname,a.lname,a.dob_month,a.dob_year
FROM new_person a LEFT JOIN person b
USING (fname,enter code herelname,dob_month,dob_day,dob_year,gender,zipcode)
WHERE (b.fname is null and b.lname is null and b.dob_year is null and b.dob_month is null)
The issue is, when I tested this query it it still shows me records that DO exist. I believe it has to do with the zipcode being null though i don't know why..
The "new_person" table only has 2 records that don't exist in the "person" table, but when i run this query it gives me 111 records.
However, if i remove the zipcode from the join clause it shows me the correct result of 2 records.
Any help would be appreciated.
You can try using EXISTS like
SELECT a.fname,
a.lname,
a.dob_month,
a.dob_year
FROM new_person a
WHERE NOT EXISTS (
SELECT 1 FROM person WHERE fname <> a.fname);
(OR) even using LEFT JOIN what you have already tried
SELECT a.fname,
a.lname,
a.dob_month,
a.dob_year
FROM new_person a
LEFT JOIN person b ON a.fname = b.fname
WHERE b.fname is null;
Again, I see that you are joining on all the columns. Not sure why? Is there any relationship exists between the tables? If so, then try joining on that related column rather.

Is it possible to build a query that does the update first with where and join conditions and if update exists then inserts?

I need to update a table which has been joined with several tables to extract the data and if the update fails then inserts the data in a new row...
currently I have a update query
.....
and I am thinking if the above query fails it should insert
INSERT INTO ASSET_ASSOCIATION.....
Thanks ...
Impossible to give you a full answer with the limited details above, but as Loopo says you can use INSERT....ON DUPLICATE KEY UPDATE . For example, based on your UPDATE:-
INSERT INTO ASSET_ASSOCIATION(ASSET_ID, ASSOCIATED_ASSET_ID, ASSET_FIELD_ID)
SELECT a.ID, b.ID, 46
FROM ASSET a
INNER JOIN HD_TICKET ON HD_TICKET.CUSTOM_FIELD_VALUE2 = a.NAME
INNER JOIN USER U ON U.ID = HD_TICKET.SUBMITTER_ID
INNER JOIN ASSET b ON U.FULL_NAME LIKE BINARY CONCAT('%',b.NAME,'%') AND b.NAME <> ''
WHERE ASSET.ASSET_TYPE_ID = 5
AND HD_TICKET.ID = 120
ON DUPLICATE KEY UPDATE ASSOCIATED_ASSET_ID=VALUES(ASSOCIATED_ASSET_ID)
This is assuming you have a unique key on asset_id and asset_field_id. However almost certain your table is more complex than this.

How to make Table Joins in PHPmyAdmin

I have 2 Tables in phpmyadmin that need joining
tracklisting is my one and catelogue is the other, and are saved as innodb
They both have a column CAT.NO and would like it to be joined on this column. In catelogue it is the primary and in tracklisting it's indexed
catelogue is my parent and tracklisting would be the child as it doesn't have info for every record in catelogue. I believe this would be correct unless I'm wrong
How do I do this so that when I query on a column in tracklisting it only brings up the matches for 'catelogue' because I want to know what album it's on and not my entire 60000+ catelogue
Can this be done with phpmyadmin's interface or is this a sql statement
Many thanks
EDIT:
This was the code that worked
SELECT *
FROM tracklisting
INNER JOIN catelogue ON catelogue.`CAT NO.` = tracklisting.`TRACKLISTING CAT NO.`
WHERE tracklisting.`ARTIST` LIKE 'placebo'
Thanks to everyone that helped out
I dont know if this can be done with the interface, but with sql
SELECT *
FROM
tracklisting t
INNER JOIN catelouge c on c.catno=t.catno
WHERE t.id = 1
You can query with a LEFT JOIN:
SELECT * FROM tracklisting LEFT JOIN catelogue ON tracklisting.`CAT.NO` = catelogue.`CAT.NO` WHERE tracklisting.`<id-field>` = <id-value>`
http://dev.mysql.com/doc/refman/5.0/en/join.html
Assuming that your tracklisting has an id and you want to query with it:
select * from tracklisting t
inner join catelogue c on c.cat.no = t.cat.no
where t.id = 1
The actual join takes place in a SQL statement although with certain storage types like InnoDB you can also create foreign key references that enforce the relationship at the database level so that your inserts require the proper records to be in place and your deletes are restricted if child records exist.
Here is one way of doing the join syntax for your SQL query:
SELECT t.* FROM tracklisting t, catalogue c
WHERE `t.CAT.NO` = `c.CAT.NO`
EDIT: Here is a link to a tutorial for creating foreign keys in phpMyAdmin.

MySQL JOIN tables with WHERE clause

I need to gather posts from two mysql tables that have different columns and provide a WHERE clause to each set of tables. I appreciate the help, thanks in advance.
This is what I have tried...
SELECT
blabbing.id,
blabbing.mem_id,
blabbing.the_blab,
blabbing.blab_date,
blabbing.blab_type,
blabbing.device,
blabbing.fromid,
team_blabbing.team_id
FROM
blabbing
LEFT OUTER JOIN
team_blabbing
ON team_blabbing.id = blabbing.id
WHERE
team_id IN ($team_array) ||
mem_id='$id' ||
fromid='$logOptions_id'
ORDER BY
blab_date DESC
LIMIT 20
I know that this is messy, but i'll admit, I am no mysql veteran. I'm a beginner at best... Any suggestions?
You could put the where-clauses in subqueries:
select
*
from
(select * from ... where ...) as alias1 -- this is a subquery
left outer join
(select * from ... where ...) as alias2 -- this is also a subquery
on
....
order by
....
Note that you can't use subqueries like this in a view definition.
You could also combine the where-clauses, as in your example. Use table aliases to distinguish between columns of different tables (it's a good idea to use aliases even when you don't have to, just because it makes things easier to read). Example:
select
*
from
<table> as alias1
left outer join
<othertable> as alias2
on
....
where
alias1.id = ... and alias2.id = ... -- aliases distinguish between ids!!
order by
....
Two suggestions for you since a relative newbie in SQL. Use "aliases" for your tables to help reduce SuperLongTableNameReferencesForColumns, and always qualify the column names in a query. It can help your life go easier, and anyone AFTER you to better know which columns come from what table, especially if same column name in different tables. Prevents ambiguity in the query. Your left join, I think, from the sample, may be ambigous, but confirm the join of B.ID to TB.ID? Typically a "Team_ID" would appear once in a teams table, and each blabbing entry could have the "Team_ID" that such posting was from, in addition to its OWN "ID" for the blabbing table's unique key indicator.
SELECT
B.id,
B.mem_id,
B.the_blab,
B.blab_date,
B.blab_type,
B.device,
B.fromid,
TB.team_id
FROM
blabbing B
LEFT JOIN team_blabbing TB
ON B.ID = TB.ID
WHERE
TB.Team_ID IN ( you can't do a direct $team_array here )
OR B.mem_id = SomeParameter
OR b.FromID = AnotherParameter
ORDER BY
B.blab_date DESC
LIMIT 20
Where you were trying the $team_array, you would have to build out the full list as expected, such as
TB.Team_ID IN ( 1, 4, 18, 23, 58 )
Also, not logical "||" or, but SQL "OR"
EDIT -- per your comment
This could be done in a variety of ways, such as dynamic SQL building and executing, calling multiple times, once for each ID and merging the results, or additionally, by doing a join to yet another temp table that gets cleaned out say... daily.
If you have another table such as "TeamJoins", and it has say... 3 columns: a date, a sessionid and team_id, you could daily purge anything from a day old of queries, and/or keep clearing each time a new query by the same session ID (as it appears coming from PHP). Have two indexes, one on the date (to simplify any daily purging), and second on (sessionID, team_id) for the join.
Then, loop through to do inserts into the "TempJoins" table with the simple elements identified.
THEN, instead of a hard-coded list IN, you could change that part to
...
FROM
blabbing B
LEFT JOIN team_blabbing TB
ON B.ID = TB.ID
LEFT JOIN TeamJoins TJ
on TB.Team_ID = TJ.Team_ID
WHERE
TB.Team_ID IN NOT NULL
OR B.mem_id ... rest of query
What I ended up doing is;
I added an extra column to my blabbing table called team_id and set it to null as well as another field in my team_blabbing table called mem_id
Then I changed the insert script to also insert a value to the mem_id in team_blabbing.
After doing this I did a simple UNION ALL in the query:
SELECT
*
FROM
blabbing
WHERE
mem_id='$id' OR
fromid='$logOptions_id'
UNION ALL
SELECT
*
FROM
team_blabbing
WHERE
team_id
IN
($team_array)
ORDER BY
blab_date DESC
LIMIT 20
I am open to any thought on what I did. Try not to be too harsh though:) Thanks again for all the info.