JOIN two query results (having WHERE and IN clauses + sub queries) - mysql

Trying to recreate the problem below (not including IN clause and sub-queries):
/* this is query 1 */
Select A.column_1,B.keyValue from table1 as A, table2 as B where
A.someColumn = B.someColumn and B.someotherColumn = 10
/* query 1 gives */
column1 | keyValue
_________________
data-A1 | key-1
data-A2 | key-2
data-A3 | key-3
/* this is query 2 */
Select AVG(ratings) as ratings, C.keyValue from table3 as C,
table4 as D where C.someColumn = D.someColumn and D.someotherColumn = 'abc'
/* query 2 gives */
ratings | keyValue
_________________
rating-1 | key-1
rating-2 | key-2
rating-3 | key-3
/* this is the desired result */
column1 | ratings | keyValue
_________________
data-A1 | rating-1 | key-1
data-A2 | rating-2 | key-2
data-A3 | rating-3 | key-3
I googled it up, found mysql join is the solution
SELECT table1.id, table2.column1, table1.column2 FROM table1
INNER JOIN table2 ON table1.id = table2.id;
But this a very basic example involving only two tables, my first query actually involves 5 tables and second query involves 4 tables with multiple WHERE and IN clauses + sub queries. I am unable to implement this JOIN logic with my complex queries having. This is what I tried but its giving me an error after "JOIN" keyword :
Select * from (Select A.column_1,B.keyValue from table1 as A, table2 as B
where A.someColumn = B.someColumn and B.someotherColumn = 10) as first
JOIN
Select * from (Select AVG(ratings) as ratings, C.keyValue from table3 as C,
table4 as D where C.someColumn = D.someColumn and D.someotherColumn = 'abc')
as second ON first.keyValue = second.keyValue;
Any help would be appreciated.

I don't know the structure of your 4 tables but based on your 2 queries, you can do the following:
select
X.column_1,
Y.ratings,
X.key_value
From
(
Select
A.column_1,
B.keyValue
from
table1 as A,
table2 as B
where
A.someColumn = B.someColumn
and B.someotherColumn = 10
)
X
INNER JOIN
(
Select
AVG(ratings) as ratings,
C.keyValue
from
table3 as C,
table4 as D
where
C.someColumn = D.someColumn
and D.someotherColumn = 'abc'
)
Y
on X.keyvalue = Y.keyvalue;
X and Y are called derived tables.
P.S: It might be possible to create a better query if we know the structure of your underlying tables, sample data and what you are trying to achieve. This is the best answer I can give you based on the information.

Related

How to join two tables with one-to-many relationship in SQL?

I have these two simple tables in MS access or MySQL.
I want to find what are the products ordered by customer B ?
what SQL query should i write?
I tried this.. why its wrong!!
SELECT PRODUCT FROM table1
INNER JOIN table2
ON table1.CUST_ID=table2.CUST_ID
WHERE table1.NAME='B' ;
This may be a very easy question, but please answer...i want to learn, Thank you very much..
You can use exists
select
product
from product p
where exists (
select
cust_id
from customer c
where p.cust_id = c.cust_id
and name = 'B'
)
output:
| product |
| ------- |
| K |
| M |
Please use below query,
select * from table1 t1
inner join table2 t2
on (t1.cust_id = t2.cust_id)
where
t1.name = 'B'

Join columns with specific match case

I have two tables TableA and TableB.
The TableA having column called Code Like
'A'
'AB'
'B'
'BB'
In TableB I have column called pnrcode like
'A001'
'AB001'
'B001'
'BC001'
Both tables have no relationship.
I want to join this two table based on TableA code with TableB pnrcode with matching the characters based on TableA
If you are using MySql 8.* you can use REGEXP_SUBSTR in a subquery to join the two tables
SELECT a.*, b.prncode
FROM TableA a
JOIN (SELECT *, REGEXP_SUBSTR(prncode, '^[A-Z]+') as code
FROM TableB) b ON a.code = b.code
Try this below code with a join. You can use any join based on your requirement.
SELECT *
FROM TableA
INNER JOIN TableB
ON TableA.Code =
left( TableB.pnrcode, length(TableB.pnrcode) - length( reverse( concat(TableB.pnrcode, "1") ) + 0 ) + 1 );
You can use replace() to remove code from pnrcode.
If what is left is a number > 0 (MySql does implicit conversion) then join on that:
select *
from tablea a left join tableb b
on replace(b.pnrcode, a.code, '') > 0
I assume that all pnrcodes have numeric part other than 0.
See the demo.
Results:
| code | pnrcode |
| ---- | ------- |
| A | A001 |
| AB | AB001 |
| B | B001 |
| BB | |
with res as
(SELECT dbo.AlphaOnly(a.Prccode) as Prccode1,* from TableA a)
SELECT * from res join Tableb b on b.Code=res.prccode1
go

How to preprocess info to match the join in the query

I have two tables, that I would like to link by its type field.
table1
id | type
---+--------
1 | One
2 | Two
3 | Three
4 | Four
5 | Two
table2
id | type
---+------
34 | N
35 | Z
26 | Y
27 | W
And the equivalent table is (this table does not exist and cannot exist)
One = Z
Two = Y
Three = N
Four = W
And my query is
SELECT t1.type
FROM table1 t1, table2 t2
WHERE t1.type = t2.type
Probably the best solution will be change the information in one of the tables. But I cannot do that, I also can't create any store procedure.
I would like to have just one query to do this.
Any idea?
You can synthesize the relationship table in the query:
SELECT t1.id AS id1, t1.type, t2.id AS id2
FROM table1 AS t1
JOIN (
SELECT 'One' AS `long`, 'Z' AS short
UNION ALL
SELECT 'Two', 'Y'
UNION ALL
SELECT 'Three', 'N'
UNION ALL
SELECT 'Four', 'W'
) AS r ON t1.type = r.long
JOIN table2 AS t2 ON t2.type = r.short
DEMO
Probably the best solution will be change the information in one of the tables. But I cannot do that, I also can't create any store procedure. I would like to have just one query to do this.
You don't necessarily have to change the information in one of the two tables. You could create a table which contains the relationships between the two types, i.e.:
table3
type1 | type2
------+------
One | Z
Two | Y
Three | N
Four | W
Then you could write a query like this:
SELECT table1.type
FROM table1
JOIN table3
ON table1.type = table3.type1
JOIN table2
ON table3.type2 = table2.type

mySQL combining two tables I get more results

I have one table of like this
user|itemID
and another table like this:
itemID | itemTrait1 | itemTrait2 etc...
I am trying to link the tables in one query which should be simple. I conduct the query like so:
SELECT * FROM Table1, Table2 WHERE Table1.userID = 1 AND Table1.itemID = Table2.itemID;
The issue is that I am getting 456 results returned but if I simply run:
SELECT * FROM Table1 WHERE userID = 1;
I get 434 results. Should both these statements get the same number of results returned?
How I imagine this call working is that for every entry in Table 1 for user 1 it connects it to the item's data in Table2? I think I am missing something here.
Query to combine both tables based in itemID
select * from table1 t1
left join table t2 on t1.itemID = t2.itemID
where t1.itemID = 1;
if you are getting the more records than the records that of table1 then your second table table2 must have multiple records for itemID. for example
Table1
user | itemId
---------------
1 | 1
Table2
itemId | itemTrait1 | itemTrait2
----------------------------------------
1 | A | B
1 | C | D
now when you will apply join here it will join itemID 1 with two items of second table.

Select all rows that have same ID

I have this table:
ID | Part
1 | A
1 | B
1 | C
2 | B
2 | C
3 | A
3 | D
3 | E
4 | B
4 | D
and want a query that will grab all ID's that have an A, and return a list of all other parts with that ID.
e.g: Want Parts related to B:
Part | Count
A | 1
C | 2
D | 1
What I have currently:
SELECT * FROM tble WHERE ID IN (SELECT DISTINCT ID FROM tble t WHERE Part = ?)
GROUP BY Part ORDER BY COUNT(Part) DESC
This works, but is quite slow and I'm looking to improve it, but having difficulty
Your query is not unreasonable, although the distinct is unnecessary and I would use exists rather than in. And, the outer select needs to be fixed for the aggregation
SELECT t.part, COUNT(*)
FROM tble t
WHERE EXISTS (SELECT 1 FROM tble t2 WHERE t2.ID = t.ID AND t2.Part = ?)
GROUP BY t.Part
ORDER BY COUNT(*) DESC;
Then, to optimize this query, you want an index:
create index idx_tble_id_part on tble(id, part);
Simplify this.. Once you have the logic down, then add back in the SELECT * FROM..
SELECT Part, COUNT(Part) As Count_of_Part
GROUP BY Part ORDER BY COUNT(Part) DESC
Do a join from the table back to itself on ID, and then count the distinct values that pop up:
SELECT b.part, COUNT(DISTINCT b.id)
FROM
table as a
INNER JOIN table as b ON
a.id = b.id AND
a.part <> b.part
WHERE
a.part = 'B'
GROUP BY b.part
This can be simply done by joining back to the table:
SELECT t1.part
,count(*)
FROM tble t1
INNER JOIN tble t ON t.id = t1.id
AND t.part = 'B'
AND t1.part <> t.part
GROUP BY t1.part
SQL Fiddle Demo
You should be able to do this by grouping the data.
Try something like this:
SELECT part, COUNT(id) AS TotalCountId
FROM TABLE_NAME
GROUP BY ID