MySQL UNION where clause condition from the first select - mysql

How can union two selections of the same tables but the second select condition depends on the first select attribute. Here is my query
SELECT *
FROM tbl_preference_header h
LEFT JOIN tbl_preference_detail d
OJ h.id = d.superid
WHERE h.type = 'CP'
UNION
SELECT *
FROM tbl_preference_header h2
LEFT JOIN tbl_preference_detail d2
ON h2.id = d2.superid
WHERE h2.type = 'GP' AND d2.cat3code NOT IN (d.cat3code)
What I want is in the second select statement it will not contain all the cat3code from first select statement. There is error in my query d is not recognized in the second select statement.
How can I accomplish this ? What another method can I use other than union ?

You won't be able to reference the original query directly, but you could bring the original query into a subquery as follows:
SELECT * FROM tbl_preference_header h left join tbl_preference_detail d on h.id = d.superid where type = 'CP'
union
select *
from
tbl_preference_header h2
left join tbl_preference_detail d2 on h2.id = d2.superid
where type = 'GP' and d2.cat3code not in (
select d.cat3code
from
tbl_preference_header h
left join tbl_preference_detail d on h.id = d.superid
where type = 'CP'
)

It is a bit hard to figure out exactly what you want. If I assume that type is part of tbl_preference_detail, then your query is equivalent to:
SELECT *
FROM tbl_preference_header h left join
tbl_preference_detail d
on h.id = d.superid
WHERE d.type = 'CP' or
(d.type = 'GP' and
not exists (select 1
from tbl_preference_detail d2
where d2.cat3code = d.cat3code and
d2.type = 'CP'
)
)

Related

Cross apply in MY SQL

Am trying to convert this Sql server script to mysql.
SELECT A.*
FROM TableA A
CROSS APPLY
(
SELECT TOP 1 UID
FROM TableB
WHERE BetID = A.BetID
AND BETCODE = A.BETCODE
ORDER BY CASE WHEN InfoCode > '' THEN 0 ELSE 1 END,UID
)Z
WHERE Z.UID = A.UID
Can please advise as how, I know I can change CROSS JOIN and Limit 1 but still it fails
in you can't use TOP but use limit so you could try and in MySql the scope for subquery table is differente respect to SQL_SERVER so you must buil the join inside the subquery
SELECT A.*
FROM TableA A
CROSS JOIN
( SELECT UID
FROM TableB
INNER JOIN TABLEA A ON BetID = A.BetID
AND BETCODE = A.BETCODE
ORDER BY CASE WHEN InfoCode > '' THEN 0 ELSE 1 END,UID
LIMIT 1
) Z
WHERE Z.UID = A.UID
or a cross join with a single result could be also translate as an inner join
SELECT A.*
FROM TableA A
INNER JOIN
( SELECT UID
FROM TableB
INNER JOIN TABLEA A ON BetID = A.BetID
AND BETCODE = A.BETCODE
ORDER BY CASE WHEN InfoCode > '' THEN 0 ELSE 1 END,UID
LIMIT 1
) Z ON Z.UID = A.UID

How can I optimize this mysql query

I would like to ask, how can I optimize this query:
select
h.jmeno hrac,
n1.url hrac_url,
t.nazev tym,
n2.url tym_url,
ss.pocet_zapasu zapasy,
ss.pocet_minut minuty,
s.celkem_golu goly,
s.zk,
s.ck
from
hraci h
left join
(
select
hrac_id,
tym_id,
count(minut_celkem) pocet_zapasu,
sum(minut_celkem) pocet_minut
from
statistiky_stridani ss
join
zapasy z
on z.id = ss.zapas_id
join
souteze s
on s.id = z.soutez_id
join
souteze_nazev sn
on sn.id = s.soutez_id
where
s.rocnik_id = 2
group by
hrac_id
) ss on ss.hrac_id = h.id
left join
(
select
hrac_id,
tym_id,
sum(typ_id = 1 or typ_id = 3) as celkem_golu,
sum(typ_id = 4) as zk,
sum(typ_id = 5) as ck
from
statistiky st
join
zapasy z
on z.id = st.zapas_id
join
souteze s
on s.id = z.soutez_id
join
souteze_nazev sn
on sn.id = s.soutez_id
where
s.rocnik_id = 2
group by
hrac_id
) s on s.hrac_id = h.id
join
navigace n1
on n1.id = h.nav_id
join
tymy t
on t.id = ss.tym_id
join
navigace n2
on n2.id = t.nav_id
order by
s.celkem_golu desc
limit
10
Because query takes about 1,5 - 2 seconds. For example, table statistiky_stridani has about 500 000 rows and statistiky about 250 000 rows.
This returns EXPLAIN:
Thank you for your help
Don't use LEFT JOIN instead of JOIN unless you really need the empty rows.
Try to reformulate because JOIN ( SELECT ... ) JOIN ( SELECT ... ) optimizes poorly.
Please do not use the same alias (s) for two different tables; it confuses the reader.
Add the composite index INDEX(rocnik_id, soutez_id) to souteze.
LEFT JOIN ... JOIN ... -- Please add parentheses to show whether the JOIN should be before doing the LEFT JOIN or after:
either
FROM ...
LEFT JOIN ( ... JOIN ... )
or
FROM ( ... LEFT JOIN ... )
JOIN ...
It may make a big difference in how the Optimizer performs the query, which may change the speed.
There may be more suggestions; work through those and ask again (if it is still "too slow").

MySQL Update table with sum value of another table

I have a query that I can't seem to manipulate to work in a SUM function in MySQL:
Here is what I want:
UPDATE account_seeds AS a
INNER JOIN b AS b ON b.accountID = a.accountID AND a.areaID = b.areaID
INNER JOIN b_seed AS s ON s.buildingID = b.buildingID
INNER JOIN seed_class AS c ON c.seedID = s.seedID
SET a.amount = a.amount + SUM(s.amount)
WHERE b.status='active' AND a.seedID = s.seedID
Now it obviously won't let me use the SUM in the update without separating it. I have tried joining select queries but can't quite get my head around it. The basic premise being that I have multiple buildings(rows) that has a seed value that will increase total seeds of that type in the area for a particular account. Without the sum it only updates one of the buildings that has a matching seed value
UPDATE
account_seeds AS a
INNER JOIN
( SELECT b.accountID, b.areaID, s.seedID
, SUM(s.amount) AS add_on
FROM b AS b
INNER JOIN b_seed AS s
ON s.buildingID = b.buildingID
INNER JOIN seed_class AS c
ON c.seedID = s.seedID
WHERE b.status = 'active'
GROUP BY b.accountID, b.areaID, s.seedID
) AS g
ON g.accountID = a.accountID
AND g.areaID = a.areaID
AND g.seedID = a.seedID
SET
a.amount = a.amount + g.add_on ;
Maybe you can use a nested query:
UPDATE account_seeds AS a
INNER JOIN b AS b ON b.accountID = a.accountID AND a.areaID = b.areaID
INNER JOIN b_seed AS s ON s.buildingID = b.buildingID
INNER JOIN seed_class AS c ON c.seedID = s.seedID
SET a.amount = a.amount + (SELECT SUM(amount) FROM b_seed)
WHERE b.status='active' AND a.seedID = s.seedID
Can you try that?

How to write a select statement inside another select in SQL

Can anyone tell me what is wrong with this query?
it gives a syntax error near the 2nd select
SELECT b.mc_boxes_idmc_boxes,
t.idtitles,
t.title,
t.languages_idlanguages,
MAX(h.idtitle_history),
MAX(h.edition)
(SELECT h.preview, h.file WHERE h.idtitle_history = MAX(h.idtitle_history))
FROM mc_boxes_has_titles b
LEFT JOIN titles t ON b.titles_idtitles = t.idtitles
LEFT JOIN title_history h ON h.titles_idtitles = t.idtitles
WHERE b.mc_boxes_idmc_boxes = 12
AND h.edition IS NOT NULL
GROUP BY b.mc_boxes_idmc_boxes, idtitles
ORDER BY b.sortorder;
looks like you are missing a comma after MAX(h.edition)
SELECT b.mc_boxes_idmc_boxes,
t.idtitles,
t.title,
t.languages_idlanguages,
MAX(h.idtitle_history),
MAX(h.edition),
(SELECT h.preview, h.file WHERE h.idtitle_history = MAX(h.idtitle_history))
FROM mc_boxes_has_titles b
LEFT JOIN titles t ON b.titles_idtitles = t.idtitles
LEFT JOIN title_history h ON h.titles_idtitles = t.idtitles
WHERE b.mc_boxes_idmc_boxes = 12
AND h.edition IS NOT NULL
GROUP BY b.mc_boxes_idmc_boxes, idtitles
ORDER BY b.sortorder;
besides the comma, you are selecting two fields in your subquery
SELECT b.mc_boxes_idmc_boxes,
t.idtitles,
t.title,
t.languages_idlanguages,
MAX(h.idtitle_history),
MAX(h.edition),
(SELECT preview FROM title_history WHERE idtitle_history = MAX(h.idtitle_history)),
(SELECT [file] FROM title_history WHERE idtitle_history = MAX(h.idtitle_history))
FROM mc_boxes_has_titles b
LEFT JOIN titles t ON b.titles_idtitles = t.idtitles
LEFT JOIN title_history h ON h.titles_idtitles = t.idtitles
WHERE b.mc_boxes_idmc_boxes = 12
AND h.edition IS NOT NULL
GROUP BY b.mc_boxes_idmc_boxes, idtitles
ORDER BY b.sortorder;
Adding to bluefeet's answer, you may want to check for reserved words. "File" for example is a reserved word in sql server.
Alias it as a virtual table. Change something like
SELECT b.mc_boxes_idmc_boxes,
t.idtitles,
t.title,
t.languages_idlanguages,
MAX(h.idtitle_history),
MAX(h.edition)
(SELECT h.preview, h.file WHERE h.idtitle_history = MAX(h.idtitle_history))
FROM mc_boxes_has_titles b
LEFT JOIN titles t ON b.titles_idtitles = t.idtitles
LEFT JOIN title_history h ON h.titles_idtitles = t.idtitles
WHERE b.mc_boxes_idmc_boxes = 12
AND h.edition IS NOT NULL
GROUP BY b.mc_boxes_idmc_boxes, idtitles
ORDER BY b.sortorder) as virtual_column_alias;
Check this out. Hope this will work.

MYSQL UNION and ORDER BY not working

I have a mysql query which is as follows
(SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable.osa_id,
order_stockavailable.of_id,
order_stockavailable.osa_stocka,
order_category.ocat_name
FROM
order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id)
UNION
(SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable_attributes.id,
order_stockavailable_attributes.of_id,
order_stockavailable_attributes.opap_stock,
order_category.ocat_name
FROM order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id
LEFT JOIN order_stockavailable_attributes
ON order_product.op_id = order_stockavailable_attributes.op_id)
ORDER BY order_product.op_name
The query is givng error, T
Table 'order_product' from one of the SELECTs cannot be used in global ORDER clause
I checked the MYSQL manual, but am not getting any clue, any help would be really great.
SELECT *
FROM (
SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable.osa_id,
order_stockavailable.of_id,
order_stockavailable.osa_stocka,
order_category.ocat_name
FROM
order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id
UNION
SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable_attributes.id,
order_stockavailable_attributes.of_id,
order_stockavailable_attributes.opap_stock,
order_category.ocat_name
FROM order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id
LEFT JOIN order_stockavailable_attributes
ON order_product.op_id = order_stockavailable_attributes.op_id
) t
ORDER BY op_name
Btw: there is no need to put the individual SELECTs of a UNION into brackets.
Try the following syntax?
SELECT
x, y
FROM
(
SELECT x, y FROM z
UNION
SELECT a, b FROM c
)
ORDER BY
x, y
Try
order by op_name
instead of
ORDER BY order_product.op_name
SELECT *
FROM (SELECT order_product.op_id,
...
FROM
... )
UNION
(SELECT order_product.op_id,
...
FROM order_product
... ) U
ORDER BY op_name;