sql get column from the 'EXISTS' statemenent - mysql

i have the following sql query
SELECT Store.*
FROM Store
WHERE EXISTS (
SELECT Contest.StoreID .....)
OR EXISTS (
SELECT Discount.StoreID .....)
my problem is that i want to include to the results some columns from the Contest and the Discount arrays. If I join them on the FROM it works but is there a way to get the values from the EXISTS ? something like this
SELECT Store.*, t1.something, t2.somethingElse
FROM Store
WHERE EXISTS (
SELECT Contest.StoreID .....) t1
OR EXISTS (
SELECT Discount.StoreID .....) t2

No, its not possible to select from the WHERE clause, think about it, this clause if for filtering.
There are two ways for selecting data from different tables together, a sub query or with a join.
Here is a JOIN example :
SELECT s.*, t1.something, t2.somethingElse
FROM Store s
LEFT OUTER JOIN Contest t1 ON(...)
LEFT OUTER JOIN Discount t2 ON(...)
WHERE t1.<column> is not null OR t2.<column> is not null
This will do the same as your query with the EXISTS() , and will probably have similar performance.
Can also be done we a correlated sub query :
SELECT * FROM (
SELECT s.*,
(SELECT t1.something FROM contest t1 WHERE t1.<col> = s.<col>) as col1,
(SELECT t1.something FROM contest t1 WHERE t1.<col> = s.<col>) as col2,
FROM Store s) t
WHERE t.col1 is not null or t.col2 is not null

Related

MySQL SELECT in SELECT-clause or in WHERE-clause in order to filter further

I'm trying to filter some data, but as the data comes from 2 tables in the database I have to union them together, permitting nulls from the second table as I always need to have any values available in the first table, due to this being a product database with some products having sub-combinations and some none. Thus far I've come up with using a Union to join the two tables together, but now I need a method to filter out the data using a WHERE clause; however: this is where I get stuck. I tried putting the union as a select statement in the FROM clause: no data returned, I tried to put it into the SELECT clause as a sub: no data returned...
In short I need something like this:
SELECT id_product, id_product_attribute,upc1,upc2
FROM (UNION)
WHERE upc1='xyz' OR upc2='xyz';
where for example the result might be things such as:
-> 100, null, 9912456, null
or
-> 200, 153, 9915559, 9977123
Currently I have this (sorry I don't have more):
(SELECT product.id_product as id_product,
product.upc as upc1,
comb.id_product_attribute,
comb.upc as upc2
FROM `db`.table1 product
LEFT JOIN `db`.table2 comb
ON comb.id_product = product.id_product
)
UNION
(SELECT product.id_product as id_product,
product.upc as headCNK,
comb.id_product_attribute,
comb.upc
FROM `db`.table1 product
RIGHT JOIN `db`.table2 comb
ON comb.id_product = product.id_product
);
Also note that upc1 is coming from table 1, and upc2 from table2.
I could use the entire query, and filter out everything using some business logic in the worst case scenario, but rather not as I don't want to perform endless queries where I don't have to, my service provider doesn't like that...
UPDATE:
I also tried:
SELECT *
from db.t1 as prod
CROSS JOIN db.t2 as comb ON prod.id_product = comb.id_product
WHERE prod.upc = 'xyz' OR comb.upc = 'xyz';
This didn't work either.
Placed a fiddle here with some small sample data:
http://sqlfiddle.com/#!9/340d7d
The output for the '991002' used in the where clause in query SELECT id_product, id_product_attribute, table1.upc, table2.upc should be: 101, null, 991002, null
And for '990001' it should then be: 101, 201, 990001, 990001
For all values try
SELECT t1.id_product, t2.id_product_attribute, t1.upc, t2.upc
FROM ( SELECT upc FROM table1
UNION
SELECT upc FROM table2 ) t0
LEFT JOIN table1 t1 USING (upc)
LEFT JOIN table2 t2 USING (upc)
For definite upc value edit to
...
SELECT t1.id_product, t2.id_product_attribute, t1.upc, t2.upc
FROM ( SELECT 990001 upc ) t0
LEFT JOIN table1 t1 USING (upc)
LEFT JOIN table2 t2 USING (upc)
...

MySql joining table with condition [duplicate]

I have a table id1, id2, type. type is an enumerated value containing a name of another table.
I'd like to preform a join with the name of the table of type.
For example:
switch($type)
case 'table1':
join table1;
break;
case 'table2':
join table2;
break;
How can I achieve this?
You can't do it directly like that... you can do something like this though (not very pretty...):
SELECT
t.id,
t.type,
t2.id AS id2,
t3.id AS id3
FROM t
LEFT JOIN t2 ON t2.id = t.id AND t.type = 't2'
LEFT JOIN t3 ON t3.id = t.id AND t.type = 't3'
ugly way:
Table Types, T1, T2:
SELECT ... FROM Types, T1 , where Types.ID=T1.Types_ID AND Types.TYPE='TABLE1'
UNION
SELECT ... FROM Types, T2 , where Types.ID=T2.Types_ID AND Types.TYPE='TABLE2'
In addition to previous answer:
You can combine the two left joins results by using IF statement:
IF(t.type= 't2', t2.id, t3.id) as type_id
You can see another mysql conditional joins example at mysqldiary.com
I needed to implement such a thing with Laravel Query Builder. I was preparing a library and shouldn't rebuild the whole query, I wanted to utilize Eloquent as much as possible so I could only add a join to the query. This could be a little closer to what you want but also a lot uglier than you would expect:
SELECT
`comments`.*,
`commentable`.`created_at` AS `commentable_created_at`
FROM
`comments`
LEFT JOIN ((
SELECT
*,
CONCAT('post_', `id`) AS `morphed_key`
FROM
`posts`)
UNION (
SELECT
*,
CONCAT('image_', `id`) AS `morphed_key`
FROM
`images`)) AS `commentable` ON
CONCAT(`comments`.`commentable_type`, '_', `comments`.`commentable_id`)= `commentable`.`morphed_key`
The point of using this way is that you are now able to add WHERE clauses like WHERE commentable.owner_id=?

select from table based on select distinct from another table

the case is that I need to select a field distinct from table1 (no duplicates) and use the result as a key to select from another table2. And I need this to be in one query. Is this possible?!
table1: hID, hName, hLocation
table2: hID, hFrom, hTo, hRate, hRoomType, hMeals
I want to correct version of this query:
SELECT
*
FROM
table1
JOIN (
DISTINCT
hID
FROM
table2
WHERE
hRoomType = Double Room
ON table1.hID = table2.hID)
expected result: all hotels that offer Double Room thanks much –
thanks for help!
Your question is quite vague and confusing. Is this what you are looking for:
SELECT hID, name, location
FROM table2
INNER JOIN table1
ON table1.hID = table2.hID
GROUP BY table2.hID;
Here is a skeleton to achieve this:
SELECT
* -- Don't forget to list the requested fields instead of using `*`!
FROM (
-- This is the distinct list from table1
SELECT DISTINCT
id
FROM
table1 T1
) DT1
INNER JOIN table2 T2
ON T1.id = T2.reference_to_t1_id
Another solution if you don't want to retrieve any columns from table1:
SELECT
* -- Don't forget to list the requested fields instead of using `*`!
FROM
table2 T2
WHERE
-- Sais that get all record from table2 where this condition matches
-- at least one record
EXISTS (
SELECT 1 FROM table1 T1 WHERE T1.id = T2.reference_to_t1_id
)
For your tables and question
SELECT
hID, hName, hLocation
FROM
table1 T1
WHERE
EXISTS (
SELECT 1 FROM
table2 T2
WHERE
T1.hID = T2.hID
AND T.hRoomType = 'Double' -- Assuming that this is the definition of double rooms
)

subquery that uses a value from the outer query in the where caluse

I wanna run a subquery that uses the value of the outer query in its where clause. Here's and example of what I wanna do:
SELECT * FROM `tbl1`
WHERE `tbl1`.`max_count` < (
SELECT COUNT(*) rc FROM `tbl2`
WHERE `tbl2`.`id` = `tbl1`.`id
)
There is tbl1 with a column named max_count, and there is tbl2 with rows referring to a row in tbl1(many-to-one relationship). What I wanna do is select rows in tbl1 where the number of rows in tbl2 referencing it is less than the max_count value of that row. But I'm pretty sure that what I wrote here, ain't gonna cut it. Any ideas?
Thanks a lot
try this -
SELECT * FROM `tbl1` t1
WHERE t1.`max_count` < (
SELECT COUNT(*) FROM `tbl2` t2
WHERE t2.`id` = t1.`id`
)
try using JOIN.
SELECT DISTINCT a.*
FROM tb1 a
INNER JOIN
(
SELECT id, COUNT(*) totalCount
FROM tbl2
GROUP BY id
) b ON a.ID = b.ID
WHERE a.max_count < b.totalCount
As an alternate solution, it's probably easier to just use a LEFT JOIN with HAVING than a subquery;
SELECT tbl1.*, COUNT(tbl2.id) current_count
FROM tbl1
LEFT JOIN tbl2
ON tbl1.id=tbl2.id
GROUP BY tbl1.id
HAVING COUNT(tbl2.id) < max_count
An SQLfiddle to test with.
Note that the GROUP BY in this case is a MySQL only thing, normally you'd need to GROUP BY every selected field in tbl1 even if tbl1.id is known to be unique per row.

conditional join in mysql

I have a table id1, id2, type. type is an enumerated value containing a name of another table.
I'd like to preform a join with the name of the table of type.
For example:
switch($type)
case 'table1':
join table1;
break;
case 'table2':
join table2;
break;
How can I achieve this?
You can't do it directly like that... you can do something like this though (not very pretty...):
SELECT
t.id,
t.type,
t2.id AS id2,
t3.id AS id3
FROM t
LEFT JOIN t2 ON t2.id = t.id AND t.type = 't2'
LEFT JOIN t3 ON t3.id = t.id AND t.type = 't3'
ugly way:
Table Types, T1, T2:
SELECT ... FROM Types, T1 , where Types.ID=T1.Types_ID AND Types.TYPE='TABLE1'
UNION
SELECT ... FROM Types, T2 , where Types.ID=T2.Types_ID AND Types.TYPE='TABLE2'
In addition to previous answer:
You can combine the two left joins results by using IF statement:
IF(t.type= 't2', t2.id, t3.id) as type_id
You can see another mysql conditional joins example at mysqldiary.com
I needed to implement such a thing with Laravel Query Builder. I was preparing a library and shouldn't rebuild the whole query, I wanted to utilize Eloquent as much as possible so I could only add a join to the query. This could be a little closer to what you want but also a lot uglier than you would expect:
SELECT
`comments`.*,
`commentable`.`created_at` AS `commentable_created_at`
FROM
`comments`
LEFT JOIN ((
SELECT
*,
CONCAT('post_', `id`) AS `morphed_key`
FROM
`posts`)
UNION (
SELECT
*,
CONCAT('image_', `id`) AS `morphed_key`
FROM
`images`)) AS `commentable` ON
CONCAT(`comments`.`commentable_type`, '_', `comments`.`commentable_id`)= `commentable`.`morphed_key`
The point of using this way is that you are now able to add WHERE clauses like WHERE commentable.owner_id=?