Multiple select queries in WHERE IN statement - mysql

I have the following sql query :
SELECT `main_table`.* FROM `prd_brand` AS `main_table`
INNER JOIN
(SELECT DISTINCT value from catalog_product_entity_int where row_id in
(select row_id from catalog_product_entity_int where attribute_id = 97 and value = 1) ,
(select row_id from catalog_product_entity_int where attribute_id = 99 and value = 4)) t
ON main_table.brand_id = t.value
Is that possible to add multiple select queries in the WHERE IN statement.
BTW, when executing the query I have #1248 - Every derived table must have its own alias.

I'm not quite sure what your query is trying to do. But this seems like a simpler way to write the logic:
SELECT b.*
FROM `prd_brand` AS b INNER JOIN
(SELECT DISTINCT value
FROM catalog_product_entity_int
WHERE (attribute_id, value) IN ( (97, 1), (99, 4) )
) t
ON b.brand_id = t.value

Related

Wrong count result in mysql when joining two tables

I am trying to join two tables and get the count and grouped by specific field. However, it outputs same count values even if the other table consist only two rows. How should I fix this?
Here's my code:
SELECT tbl1.preferredDay, COUNT(tbl1.preferredDay) as count_1, COUNT(tbl2.preferredDay) as count_2
FROM tblschedule as tbl1
LEFT JOIN tblappointments as tbl2 ON (tbl1.preferredDay = tbl2.preferredDay)
WHERE tbl1.preferredDay = tbl2.preferredDay
GROUP BY preferredDay;
Here is the output but it should be [15, 0][3, 3]
Your query is based on left join it will return the same count().
This is a working query for Mysql 8:
with tbl1 as (
SELECT preferredDay, count(1) as count_1
FROM tblschedule
GROUP BY preferredDay
),
tbl2 as (
SELECT preferredDay, count(1) as count_2
FROM tblappointments
GROUP BY preferredDay
)
select t1.preferredDay, t1.count_1, t2.count_2
from tbl1 t1
inner join tbl2 t2 on t1.preferredDay = t2.preferredDay
There are two WITHs to get separately the count and then an INNER JOIN to join those results
For Mysql 5.7 and lower :
select t1.preferredDay, t1.count_1, t2.count_2
from (
SELECT preferredDay, count(1) as count_1
FROM tblschedule
GROUP BY preferredDay
) as t1
inner join (
SELECT preferredDay, count(1) as count_2
FROM tblappointments
GROUP BY preferredDay
) as t2 on t1.preferredDay = t2.preferredDay

Sort MySql query by field in exists sub query

I am looking for a way to sort a query by a field that exists within a where exists query.
An attempt to use a field from the exists subquery I get the 'Unknown column' error.
Example query;
select
*
from
`table_a`
where
`a_field` = 'foo'
and exists (
select
*
from
`table_b`
where
`table_a`.`an_id` = `table_b`.`another_id` and `table_b`.`another_field` = 'bar'
)
order by
`table_a`.`created_at` asc,
`table_b`.`another_id` desc;
Is the only solution to use an inner join query like;
select
`t1`.*
from
`table_a` as `t1`
inner join `table_2` as `t2` on `t2`.`another_id` = `t1`.`an_id`
where
`t1`.`a_field` = 'foo'
and `t2`.`another_field` = 'bar'
order by
`t1`.`created_at` asc,
`t2`.`another_id` desc;
Your example query is ordering by another_id, which is used in the correlation clause. So, you can just do:
select a.*
from table_a a
where a.a_field = 'foo' and
exists (select 1
from table_b b
where a.an_id = b.another_id and
b.another_field = 'bar'
)
order by a.created_at asc,
a.an_id desc;
Assuming you actually want a different column, you can use a JOIN. The issue is that more than one row may match. So you need to remove the duplicates in the subquery:
select a.*
from table_a a join
(select b.another_id, max(b.another_col) as another_col
from table_b b
where another_field = 'bar'
group by b.another_id
) b
on a.an_id = b.another_id
where a.a_field = 'foo'
order by a.created_at asc, b.another_id desc;
You can only use your form of the JOIN if you know that at most one row will match.

Two join statements gives Unknown column

I have this SQL query :
SELECT `main_table`.* FROM `ves_brand` AS `main_table`
INNER JOIN
(SELECT DISTINCT value from catalog_product_entity_int
where row_id in
(select row_id from catalog_product_entity_int
WHERE (attribute_id, value) IN ( (99, 4) ))) AS `t`
ON main_table.brand_id = t.value
INNER JOIN `catalog_product_entity` AS `cpeiz`
ON cpeiz.row_id = catalog_product_entity_int.row_id
WHERE (cpeiz.attribute_set_id != 19)
This gives the error:
#1054 - Unknown column 'catalog_product_entity_int.row_id' in 'on clause'
Even if I set an alias for the column catalog_product_entity_int.row_id, the column is always "unknown".
catalog_product_entity_int is defined inside your subquery, you can't reference it directly from outside your subquery. (think of it like a local variable, you have to pass it back somehow to the main query)
Very dependent on your dataset, but something like this will work
SELECT `main_table`.* FROM `ves_brand` AS `main_table`
INNER JOIN
(SELECT DISTINCT value, row_id from catalog_product_entity_int
where row_id in
(select row_id from catalog_product_entity_int
WHERE (attribute_id, value) IN ( (99, 4) ))) AS `t`
ON main_table.brand_id = t.value
INNER JOIN `catalog_product_entity` AS `cpeiz`
ON cpeiz.row_id = t.row_id
WHERE (cpeiz.attribute_set_id != 19)

update 25 % of total rows returned by a select query

I have to insert data into a table with columns ( col 1, col2, col 3) .
I have a select query to select the data to be inserted in this table.
Select A.id, b.id , '1'
from table a
inner join table b on a.id=b.id
where a.col= 'somevalue'and b.col ='othervalue' ...
If you notice the third column in the select statment i have a hard coded value '1'. The current requirement is to set only the 25 % of the total rows with '1' and rest 75 % with '0'. Now the difficult part is we cant be sure how many rows the select statement will come up with.
We can also use an update statement to update the 25 % rows with 1 and rest keep it as '0' but the limit fucntion will not accept any user defined variable.
Can anyone suggest something on this ?
I am using MYSQL
When you insert the data into the table, keep a row number, and use modulo arithmetic:
insert into . . .
select a_id, b_id, (mod(rn, 4) = 0) as flag
from (Select A.id as a_id, b.id as b_id , (#rn := #rn + 1) as rn
from table a inner join
table b
on a.id = b.id cross join
(select #rn := 0) vars
where a.col = 'somevalue' and b.col = 'othervalue' ...
) i;
One nice feature of taking every fourth row is that this works well, even if the data is somehow ordered because of the join.
Use a subquery to get the total number of rows. Then use a user-defined variable to get the row number in the output, and compare it to 25% of the total.
SELECT a.id, b.id, IF(#counter < pct25, '1', '0'), #counter := #counter + 1
FROM table1 a
JOIN table2 b ON a.id = b.id
JOIN (SELECT COUNT(*)/25 AS pct25
FROM table1 a
JOIN table2 b ON a.id = b.id) AS x
CROSS JOIN (SELECT #counter := 0) AS var

compare two values in sql with eachother

I have a database of magento with double images, I want to delete those but first i got to detect them with a sql query.
I have tried this code
select t1.VALUE from catalog_product_entity_media_gallery t1
join catalog_product_entity_media_gallery t2 on (t1.value = t2.value)
this one:
select * from catalog_product_entity_media_gallery where value=value
and this one:
select
*
from
(
select
value
from
catalog_product_entity_media_gallery
group by
value
having count(*) > 1
) as t
inner join catalog_product_entity_media_gallery on (
catalog_product_entity_media_gallery.value = t.value
)
the first gives an error and the second- and third one gives back every product.
Give this one a try:
select
*
from (
select
entity_id,attribute_id,value,
MIN(value_id) value_id
from catalog_product_entity_media_gallery
group by
entity_id,attribute_id,value
having COUNT(*) > 1
) A1
inner join catalog_product_entity_media_gallery A2 on
A1.entity_id = A2.entity_id and
A1.attribute_id = A2.attribute_id and
A1.value = A2.value and
A1.value_id = A2.value_id
You can just get the min id by value, then except the other records:
select
*
from catalog_product_entity_media_gallery t1
where exists
( select * from
(select value, min(value_id) as min_value_id
from catalog_product_entity_media_gallery
group by value
) as t2
where t1.value=t2.value and t1.value_id=t2.min_value_id
)
If you want delete the duplicated rows, change exists to not exists.
delete
from catalog_product_entity_media_gallery t1
where not exists
( select * from
(select value, min(value_id) as min_value_id
from catalog_product_entity_media_gallery
group by value
) as t2
where t1.value=t2.value and t1.value_id=t2.min_value_id
)