Why does this query make my whole database freeze? - mysql

SELECT * FROM `groupon-spain-6sep-2011`, `Hoja1`,`GroupaliaJuly2011`
WHERE `groupon-spain-6sep-2011`.`code`= 5654
OR `Hoja1`.`code` = "5654
OR `GroupaliaJuly2011`.`code` = 5654

You are missing any join condition relating the tables to each other so are doing a cartesian join of 3 tables.
I recommend always using explicit join syntax
SELECT *
FROM `groupon-spain-6sep-2011`
JOIN `hoja1` ON `groupon-spain-6sep-2011`.foo=`hoja1`.foo
JOIN `groupaliajuly2011` ON `groupaliajuly2011`.`foo` = `hoja1`.foo
WHERE `groupon-spain-6sep-2011`.`code` = 5654
OR `hoja1`.`code` = 5654
OR `groupaliajuly2011`.`code` = 5654
Although it is possible that you might be wanting a Union here I think anyway?

You might want to do a union instead:
SELECT *
FROM groupon-spain-6sep-2011
WHERE code = 5654
UNION SELECT *
FROM Hoja1
WHERE code = 5654
UNION SELECT *
FROM GroupaliaJuly2011
WHERE code = 5654

The query you posed involves the Cartesian product(also known as CROSS JOIN in standard SQL, thanks for the advice #onedaywhen) of three tables, the amount of record involves will be size(A) * size(B) * size(C). So if the total product is large enough, it will fill a significant amount of memory, which will make your database unable to response to any other request, and that will lead to the 'freeze' of your database.
I noticed that you want either of the three specified columns to be the same value '5654', so you can selet tuples from three table respectively, and then UNION them, instead of doing Cartesian product of them like you're doing it now, since I don't think the Cartesian product you're making makes any sense. That will save a GREAT number of memory.

Related

Join to tables and String Compare (large data set)

I am very new to SQL and don't really know much about what i'm doing. I'm trying to figure out how to get a list of leads and owners whose corresponding campaign record types are stated as "inter"
So far I have tried joining the two tables and running a string compare I found on a different stack overflow page. Separately they work fine but together everything breaks... I only get the error "You have an error in your SQL syntax; check the manual"
select a.LeadId, b.OwnerId from
(select * from CampaignMember as a
join
select * from Campaign as b
on b.id = a.CampaignId)
where b.RecordTypeId like "inter%"
Schema:
Campaign CampaignMember
------------- ----------------
Id CampaignId
OwnerId LeadId
RecordTypeId ContactId
The string compare is also very slow. I am looking at a table of 600M values. Is there a faster alternative?
Is there also a way to get more specific errors in MySQL?
If you format your code properly, it will be very easy to see why it's not working.
select a.LeadId, b.OwnerId
from (
select *
from CampaignMember as a
join select *
from Campaign as b on b.id = a.CampaignId
)
where b.RecordTypeId like "inter%"
It's not a valid JOIN format. Also the last part, SQL use single quote ' instead of double quote "
Probably what you want is something like this
SELECT a.LeadId, b.OwnwerId
FROM CampaignMember a
JOIN Campaign b ON b.id = a.CampaignId
WHERE b.RecordTypeId LIKE 'inter%'
Try this:
select CampaignMember.LeadId, Campaign.OwnerId from
Campaign
inner join
CampaignMember
on CampaignMember.CampaignId= Campaign.id
where Campaign.RecordTypeId like "inter%"
MySql is generally pretty poor and handling sub-selects, so you should avoid them when possible. Also, your sub-select isn't filtering any rows, so it has to evaluate every row before applying the LIKE filter. This is sometimes "intelligently" handled by the query engine, but you should try to minimize reliance on the engine to optimize the query.
Additionally, you really should only return the columns that you care about; SELECT * is ok for confirming things, but slows queries down.
Therefore, the query posted by Eric (above) is actually the best choice.

comparing two table columns in mysql results in duplicate

I have two tables, I've been trying to print the result from each but they are being duplicated. These are the two MySQL tables and the result. Notice the duplication.
The sql code for the project is:
SELECT * FROM savings,savtype WHERE cust_id=".$_SESSION['user']
I'm also looking for a work around this, in the meantime, id appreciate any assistance on this.
because you are not specifying how the two tables are related. You need to add that, either via an explicit ... JOIN ... (USING|ON)
SELECT
*
FROM
savings JOIN savtype USING (savtype_id)
WHERE
cust_id = ".$_SESSION['user']
or by providing the criteria in the where clause.
SELECT
*
FROM
savings, savtype
WHERE
savings.savtype_id = savtype.savtype_id AND
cust_id = ".$_SESSION['user']
As I understand from the screenshot you added, it makes joint between those tables, and what you probably want it left join from savings and savtype tables.
SELECT *
FROM `savings`
LEFT JOIN `savtype`
ON savings.savtype_id=savtype.savtype_id
where cust_id=".$_SESSION['user'] .";
Update if this did the trick,
You can learn more about left join here: https://www.w3schools.com/sql/sql_join_left.asp

Union alternate to make query more efficient. Mysql

Below is my query
Select
count(t.prid)
from
(select
pr.prid
from
jcp
inner join pr ON pr.prid = jcp.prid
where
jcp.custid = 123 union select
pr.prid
from
jcl
inner join pr ON pr.prid = jcl.prid
where
jcl.custid = 123) as t
is there any way to make it more efficient? this query is inside some function and executing 1000s of time. so making it slow.
First of all, your query appears to be combining two very different types of data in your 'union' - the first part being the count of an ID, and the second being the literal ID - so I would question whether this is really doing what you intend it to do as written. However, just taking it at face value, you could eliminate the subquery in the first part as follows:
SELECT COUNT(pr.prid)
FROM jcp
INNER JOIN pr
ON pr.prid = jcp.prid
WHERE jcp.custid = 123
I can't say how much that would help your performance without knowing the context of your data, but it certainly wouldn't hurt.
Given the difference in the two data sets, it doesn't appear possible to avoid the union if you want to force these two different bits of data into the same column. If you were to put them into different columns, you could probably avoid the union.

Sql Join taking a lot of time

I am tying to execute this query but it is taking more than 5 hours, but the data base size is just 20mb. this is my code. Here I am joining 11 tables with reg_id. I need all columns with distinct values. Please guide me how to rearrange the query.
SELECT *
FROM degree
JOIN diploma
ON degree.reg_id = diploma.reg_id
JOIN further_studies
ON diploma.reg_id = further_studies.reg_id
JOIN iti
ON further_studies.reg_id = iti.reg_id
JOIN personal_info
ON iti.reg_id = personal_info.reg_id
JOIN postgraduation
ON personal_info.reg_id = postgraduation.reg_id
JOIN puc
ON postgraduation.reg_id = puc.reg_id
JOIN skills
ON puc.reg_id = skills.reg_id
JOIN sslc
ON skills.reg_id = sslc.reg_id
JOIN license
ON sslc.reg_id = license.reg_id
JOIN passport
ON license.reg_id = passport.reg_id
GROUP BY fullname
Please help me if I did any mistake
This is a bit long for a comment.
The first problem with your query is that you are using select * with group by fullname. You have zillions of columns in the select that are not in the group by. Unless you really, really, really know what you are doing (which I doubt), this is the wrong way to write a query.
Your performance problem is undoubtedly due to cartesian products and lack of indexes. You are joining across different dimensions -- such as skills and degrees. The result is a product of all the possibilities. For some people, the data size can grow and grow and grow.
And then, the question is: do you have indexes on the keys used in the joins? For performance, you generally want such indexes.
I thought the problem is in the query.First make sure group by fullname and try to give some column names instead of *.

Need help speeding up a MySQL query

I need a query that quickly shows the articles within a particular module (a subset of articles) that a user has NOT uploaded a PDF for. The query I am using below takes about 37 seconds, given there are 300,000 articles in the Article table, and 6,000 articles in the Module.
SELECT *
FROM article a
INNER JOIN article_module_map amm ON amm.article=a.id
WHERE amm.module = 2 AND
a.id NOT IN (
SELECT afm.article
FROM article_file_map afm
INNER JOIN article_module_map amm ON amm.article = afm.article
WHERE afm.organization = 4 AND
amm.module = 2
)
What I am doing in the above query is first truncating the list of articles to the selected module, and then further truncating that list to the articles that are not in the subquery. The subquery is generating a list of the articles that an organization has already uploaded PDF's for. Hence, the end result is a list of articles that an organization has not yet uploaded PDF's for.
Help would be hugely appreciated, thanks in advance!
EDIT 2012/10/25
With #fthiella's help, the below query ran in an astonishing 1.02 seconds, down from 37+ seconds!
SELECT a.* FROM (
SELECT article.* FROM article
INNER JOIN article_module_map
ON article.id = article_module_map.article
WHERE article_module_map.module = 2
) AS a
LEFT JOIN article_file_map
ON a.id = article_file_map.article
AND article_file_map.organization=4
WHERE article_file_map.id IS NULL
I am not sure that i can understand the logic and the structure of the tables correctly. This is my query:
SELECT
article.id
FROM
article
INNER JOIN
article_module_map
ON article.id = article_module_map.article
AND article_module_map.module=2
LEFT JOIN
article_file_map
ON article.id = article_file_map.article
AND article_file_map.organization=4
WHERE
article_file_map.id IS NULL
I extract all of the articles that have a module 2. I then select those that organization 4 didn't provide a file.
I used a LEFT JOIN instead of a subquery. In some circumstances this could be faster.
EDIT Thank you for your comment. I wasn't sure it would run faster, but it surprises me that it is so much slower! Anyway, it was worth a try!
Now, out of curiosity, I would like to try all the combinations of LEFT/INNER JOIN and subquery, to see which one runs faster, eg:
SELECT *
FROM
(SELECT *
FROM
article INNER JOIN article_module_map
ON article.id = article_module_map.article
WHERE
article_module_map.module=2)
LEFT JOIN
etc.
maybe removing *, and I would like to see what changes between the condition on the WHERE clause and on the ON clause... anyway I think it doesn't help much, you should concentrate on indexes now.
Indexes on keys/foreign key should be okay already, but what if you add an index on article_module_map.module and/or article_file_map.organization ?
When optimizing queries I use to check the following points:
First: I would avoid using * in SELECT clause, instead, name the diferent fields you want. This increases crazily the speed (I had one which took 7 seconds with *, and naming the field decreased to 0.1s).
Second: As #Adder says, add indexes to your tables.
Third: Try using INNER JOIN instead of WHERE amm.module = 2 AND a.id NOT IN ( ... ). I think I read (I don't remember it well, so take it carefully) that usually MySQL optimize INNER JOINS, and as your subquery is a filter, maybe using three INNER JOINS plus WHERE would be faster to retrieve.