i am getting error Lost connection to MySQL server during query with UNION query bellow.
select *
from `dealers`
where exists ((
select *
from `cars`
where `dealers`.`id` = `cars`.`dealer_id`
and exists (select *
from `dealers`
where `cars`.`dealer_id` = `dealers`.`id`)
and `dealer_id` = 27
order by `price` asc)
union (select *
from `cars`
where `dealers`.`id` = `cars`.`dealer_id`
and exists (select *
from `dealers`
where `cars`.`dealer_id` = `dealers`.`id`)
and `dealer_id` != 27
order by `price` desc))
order by `dealers`.`name` asc
Strange thing is that if i remove the last line entirely or if i sort by id instead of name it works fine.
Any ideas what could possibly be wrong with this?
Related
I have following table with around 10 million records.
and using following query to retrieve data, but it is taking more than 4, 5 seconds to hand over the response.
Is any way to improve query...?
CREATE TABLE `master` (
`organizationName` varchar(200) NOT NULL DEFAULT '',
`organizationNameQuery` varchar(200) DEFAULT NULL,
`organizationLinkedinHandle` varchar(200) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '',
`organizationDomain` varchar(110) NOT NULL DEFAULT '',
`source` varchar(10) NOT NULL DEFAULT '',
`modified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `master_inx` (`organizationName`(80),`organizationDomain`(80),`organizationLinkedinHandle`(80),`organizationNameQuery`(80),`source`),
KEY `organizationDomain` (`organizationDomain`),
KEY `domainWithModified` (`organizationDomain`,`modified`),
KEY `modifiedInx` (`modified`)
);
Query:
SELECT *
FROM (SELECT *
FROM Organizations.master
where ( ( organizationDomain like 'linkedin.com'
|| organizationNameQuery = 'linkedin.com')
and source like 'MY_SOURCE') ) M
ORDER BY M.modified DESC limit 1;
1 row in set (4.69 sec)
UPDATE
I found by breaking OR operator i am getting result faster.
For example:
SELECT *
FROM (SELECT *
FROM Organizations.master
where ( ( organizationDomain like 'linkedin.com')
and source like 'MY_SOURCE') ) M
ORDER BY M.modified DESC limit 1;
1 row in set (0.00 sec)
SELECT *
FROM (SELECT *
FROM Organizations.master
where ( (organizationNameQuery = 'linkedin.com')
and source like 'MY_SOURCE') ) M
ORDER BY M.modified DESC limit 1;
1 row in set (0.00 sec)
Use OR, not || in that context.
The performance villain is OR. Turn the OR into UNION:
( SELECT *
FROM Organizations.master
WHERE organizationDomain = 'linkedin.com'
AND source = 'MY_SOURCE'
ORDER BY modified DESC limit 1
) UNION ALL
( SELECT *
FROM Organizations.master
WHERE organizationNameQuery = 'linkedin.com'
AND source = 'MY_SOURCE'
ORDER BY modified DESC limit 1
}
ORDER BY modified DESC LIMIT 1;
Notes:
This formulation is likely to take about 0.00s to run.
The ORDER BY and LIMIT shows up 3 times.
If you need OFFSET, things get a little tricky.
Change back to LIKE if you allow users to enter wildcards.
A leading wildcard would not be efficient.
UNION ALL is faster than UNION (aka UNION DISTINCT).
It needs two new composite indexes; the order of the 2 columns is not critical:
INDEX(organizationDomain, source),
INDEX(organizationNameQuery, source)
As I checked the query I think you can remove the like operator and use =.
SELECT * FROM (
SELECT * FROM Organizations.master
where ( (organizationDomain = 'linkedin.com' ||
organizationNameQuery = 'linkedin.com')
and source = 'MY_SOURCE')
) M
ORDER BY M.modified DESC limit 1
select * from csclass where cnumber not in (
(select distinct cnumber from temp where taken=0) union (select cnumber from taken where username = "1")
);
This is what i have now. I just google it and realized that not in could not be a table. So how could i do this?
Thank you.
The below is my whole code.
create temporary table temp
(cnumber VARCHAR(45) not null
, lclass VARCHAR(45) not null
,taken boolean not null default false
);
insert into temp(cnumber,lclass)
select uclass,lclass from pre;
update temp,taken set temp.taken=true where temp.lclass=taken.cnumber;
select * from csclass where cnumber not in (
(select distinct cnumber from temp where taken=0) union(select cnumber from taken where username = "1")
);
So sorry for my bad English skill. So when i run this, there is error message: Error Code 1064. Syntax error.
So in the end i fixed this with below code:
select * from csclass where cnumber not in ( select cnumber from(
(select distinct cnumber from temp where taken=0) union (select cnumber from taken where username = "1")
) as total) ;
And Thank you guys.
SELECT * FROM (
SELECT * FROM cars WHERE site = '5'
ORDER BY cost DESC LIMIT 0 , 10
)
ORDER BY time
How would I execute a sql query like this? So first it selects the 10 cars with the highest cost, THEN it reorders those 10 cars by what time they were added to the DB.
I tried to figure it out but I just cannot get a grip on the syntax :P
Just give an alias to the sub-query.
SELECT * FROM (
SELECT * FROM `cars` WHERE `site` = '5'
ORDER BY `cost` DESC LIMIT 0 , 10
)t
ORDER BY `time`;
This query will give you the desired results
SELECT * FROM ( SELECT * FROM cars WHERE site = 5
ORDER BY cost DESC LIMIT 0 , 10 ) as t ORDER BY time
the MySQL docs say: "You cannot refer to a TEMPORARY table more than once in the same query."
I know this has been asked before. But I can't find a specific solution for the following.
I'm doing a preselection into a temporary table
CREATE TEMPORARY TABLE preselection AS SELECT ...;
now I wanna do some (around 20 or even 30) unions
(SELECT FROM preselection ...)
UNION
(SELECT FROM preselection ...)
UNION
......
UNION
(SELECT FROM preselection ...)
I could make 20 or 30 copies of preselection and do each select on each table but if I understand it right this is the same as invoke the preselection-query above in every SELECT inside the UNION chain as a subquery.
Is there a way to work around this issue?
Greetings,
chris
Full query:
CREATE TEMPORARY TABLE preselection AS
(
SELECT id, title, chapter, date2, date, snid, max(score) FROM `movies`
WHERE
(
cluster is not NULL
)
AND
(
`date` <= '2012-02-20 05:20:00'
AND `date` > '2012-02-19 17:20:00'
AND (TIMEDIFF(date, date2) < '12:00:00')
)
GROUP BY cluster
)
UNION
(
SELECT id, title, chapter, date2, date, snid, score FROM `movies`
WHERE cluster IS NULL
AND
(
`date` <= '2012-02-20 05:20:00' AND `date` > '2012-02-19 17:20:00' AND (TIMEDIFF(date, date2) < '12:00:00')
)
);
(SELECT * FROM preselection WHERE snid=1 AND chapter LIKE '#A_OT%'
DESC LIMIT 4)
UNION
…
UNION
(SELECT * FROM preselection WHERE snid=19 AND chapter LIKE '#A_OT%'
LIMIT 4)
UNION
... for each chapter from A to J and every snid from 1 to 19 ...
UNION
(SELECT * FROM preselection WHERE snid=1 AND chapter LIKE '#J_OT%'
LIMIT 4)
UNION
…
UNION
(SELECT * FROM preselection WHERE snid=19 AND chapter LIKE '#J_OT%'
LIMIT 4)
ORDER BY `score` DESC, `date`;
I think the error message is clear: you can't do that with a single temporary table. Does creating a view of the data, instead of a temporary tables, do the trick?
Views in mysql
Yes it can be frustrating. The solutions I typically use involve avoiding the temporary table with a more complex query or using more temporary tables.
A simple copy (but like you mentioned this is no use to you)
CREATE TEMPORARY TABLE preselectionCopy AS
SELECT * FROM preselection;
Or a temporary table to hold your results
CREATE TEMPORARY TABLE result (
id INT NULL,
title VARCHAR(256) NULL
...
);
...which can be as simple as
CREATE TEMPORARY TABLE result AS
SELECT * FROM preselection WHERE snid=1 AND chapter LIKE '#A_OT%'
LIMIT 4;
INSERT INTO result
SELECT * FROM preselection WHERE snid=19 AND chapter LIKE '#A_OT%'
LIMIT 4;
...
SELECT * FROM result
ORDER BY `score` DESC, `date`;
This is my query:
SELECT UID, COUNT( * ) *100 AS Points
FROM `Visited`
WHERE UID = '25'
UNION ALL
SELECT UID, COUNT( * ) *1000 AS Points
FROM `Sites`
WHERE UID = '25'
UNION ALL
SELECT UID, COUNT( * ) *1000 AS Points
FROM `userTags`
WHERE UID = '25'
When I run it, and one of the subqueries finds no results I get:
#1048 - Column 'UID' cannot be null
I don't really understand the problem, running the subquery that gives no results alone works alright and displays:
UID | POINTS
NULL 0
However the big query won't unite it for some reason. What could be the reason?
---- EDIT
Also if the three subqueries give results the query works fine. The only problem is where there are no results in one of them.
It looks like there are no matching rows for UID = 25, however COUNT(*) still returns a row saying there are 0 matching rows. You can either remove the row by using an outer select where UID is not null, or more simply replace the NULL, like this:
SELECT UID, COUNT( * ) *100 AS Points
FROM `Visited`
WHERE UID = '25'
UNION ALL
SELECT ifnull(UID, '25'), COUNT( * ) *1000 AS Points
FROM `Sites`
WHERE UID = '25'
UNION ALL
SELECT UID, COUNT( * ) *1000 AS Points
FROM `userTags`
WHERE UID = '25';
Of course, you would replace the '25' with $uid for running from your code.
Do the same for the other tables too if you think there's a chance there are no matching rows