SQL join table to selected records - mysql

Example:
SELECT SUM(SALARY) FROM (SELECT * FROM table1 WHERE id > 10) a LEFT JOIN table2 b on a.person = b.person
I want join table2 records only to (SELECT * FROM table1 WHERE id > 10) records, my example is not correct.
table1 contain 100mln records and I cant join table2 to all records I must use subquery

I'm assuming, you salary is not summing up correctly (you are getting more than you expect). This is because LEFT JOIN will leave NULL for the rowsthat doesn't have match in b.
For this SQL:
SELECT a.*, b.*
FROM (select * from (SELECT 123 AS Salary,
'Tom' AS person
UNION
SELECT 343 AS Salary,
'Bob' AS person
UNION
SELECT 877 AS Salary,
'Tom' AS person) as t where t.Salary > 123) a
LEFT JOIN (SELECT *
FROM (SELECT 'Tom' AS person,
1 AS id
UNION
SELECT 'Bob' AS person,
2 AS id) AS t
WHERE t.id = 1) AS b
ON a.person = b.person
you will have this output:
So INNER JOIN should work for you.
SELECT SUM(SALARY) FROM (SELECT * FROM table1 WHERE id > 10) a
LEFT JOIN table2 b on a.person = b.person

Hopefully this will get you going in the correct direction....
select sum(a.salary)
from table1 a
left join table2 b on a.person = b.person and b.salary_type = "something"
where a.id > 10
;

Related

add select query result from tableA as a new column in tableB

I am creating a new table from joining two tables through below query:
select a.name, a.number, b.id, b.sub_num
from tableA a left join
tableB b
on a.number = concat(id,'-',Cast(sub_num as varchar);
Here, I want to add a new column into the new table which is select query result on tableA.
The table data would be something like below:
enter image description here
I am trying to use below query which is not correct as it is giving me multiple rows. I need sum of dext_number for condition dext_id = 17501 and group by of name and number columns.
select a.name, a.number, b.id, b.sub_num,
(select sum(dext_number) from tableA where dext_id = 17501 group by name, number) as newcol
from tableA a left join tableB b
on a.number = concat(id,'-',Cast(sub_num as varchar);
What is the best way to add this column here?
use following query
select a.name, a.number, b.id, b.sub_num, (select sum(dext_number) over(partition by name, number) from tableA
where dext_id = 'xyz' limit 1) as newcol
from tableA a
left join tableB b on a.number = concat(id,'-',Cast(sub_num as varchar);
If you want the exact output of the query image, use the following query
select L.name,L.number,L.dext_id,L.dext_number,
case when L.num > 1 then newcol
else NULL
end as newcol
from
(select *,
count(dext_number) over(partition by name, number) as num,
sum(dext_number) over(partition by name, number) as newcol
from tableA) L left join tableA R on L.dext_id = R.dext_id and L.name= R.name and L.number = R.number and L.dext_number = R.dext_number
And the combination of the first query with tableB will be as follows
select a.name, a.number, b.id, b.sub_num, (select
case when L.num > 1 then newcol
else NULL
end as newcol
from
(select *,
count(dext_number) over(partition by name, number) as num,
sum(dext_number) over(partition by name, number) as newcol
from Test) L left join Test R on L.dext_id = R.dext_id and L.name= R.name and L.number = R.number and L.dext_number = R.dext_number limit 1) as newcol
from tableA a
left join tableB b on a.number = concat(id,'-',Cast(sub_num as varchar);

GROUP BY and JOIN in HIVE

How can I do something like this in HIVE:
Table1:
ID Name Friends
1 Tom 5
Table2:
ID Name DOB
1 Jerry 10/10/1999
1 Kate Null
1 Peter 02/11/1983
1 Robert Null
1 Mitchell 09/09/2000
What I want to do is:
For each ID in table 1, find num of not null DOB and then divide by Friends
I wrote a query as:
SELECT t.ID, t.Friends, COUNT(s.DOB)/ t. Friends from Table1 t join Table2 s on (t.ID = s.ID) GROUP BY t.ID
When I do this, I get the error as FRIENDS is not part of the GROUP BY Key
The answer I am expecting is: 3/5
Just add the FRIENDS to your GROUP BY section:
SELECT t.ID, t.FRIENDS, COUNT(s.DOB)/ t. FRIENDS
from Table1 t
join Table2 s
on (t.ID = s.ID)
GROUP BY t.ID. t.FRIENDS
I prefer to write this kind of query like this:
SELECT t.ID, case when t.FIREND>0 then Cnt / t.FRIENDS ELSE 0 END
FROM Table t1
JOIN (Select ID, Count(*) AS Cnt from Table 1 GROUP BY Id) t2
ON t1.ID = t2.ID
if you have declare id,friends in table 1 as integer and id in table2 as integer, then below query will get you intended output
select a.name, concat(cast(b.cnt as string),'/',cast(a.friends as string))
from table1 a
join
(select id, count(DOB) as cnt from table2 where DOB is not null group by id) b
on (a.id = b.id)

Left Join query not working

I have 2 tables.
Table 1:
ID Name Age PhoneNumber
12 Joe 25 873827382
23 Bob 28 928398233
34 Jane 23 237828883
Table 2:
ID Agent QuantitySold
12 A1 100
23 B1 300
12 C1 600
34 A2 400
34 B1 800
23 B2 900
I want to show all the details of the employees who have never sold a quantity not equal to 800.
SELECT a.ID, a.Name, a.Age, a.PhoneNumber
FROM table1 a LEFT JOIN table2 b
ON a.ID= b.ID AND b.quantity <> 800
I want a result set that doesn't have ID 34 in it. But I cant seem to achieve that. Any help?
You need to change your Left Join to Inner Join.
Left Join will bring all the rows from table1 even though he never made a sales. I will do this using Exists.
SELECT a.ID,
a.Name,
a.Age,
a.PhoneNumber
FROM table1 a
WHERE EXISTS (SELECT 1
FROM table2 b
WHERE a.ID = b.ID
AND b.quantity <> 800)
You can use NOT EXISTS without any of the JOINs:
SELECT a.ID
, a.Name
, a.Age
, a.PhoneNumber
FROM table1 a
WHERE NOT EXISTS (SELECT * FROM table2 WHERE ID = a.ID AND QuantitySold = 800)
By the way, the column name is QuantitySold, not quantity.
JSFiddle
This is what finally worked.
SELECT a.ID
, a.Name
, a.Age
, a.PhoneNumber
FROM table1 a
WHERE a.ID NOT IN (SELECT ID FROM table2 QuantitySold = 800);
Why you are using Left Join. Use inner join rather. Something like this:-
SELECT a.ID, a.Name, a.Age, a.PhoneNumber, SUM(b.quantity)
FROM table1 a JOIN table2 b
ON a.ID= b.ID
GROUP BY b.Agent
HAVING SUM(b.quantity) <> 800

MYSQL Performance Tuning with group by clause

I have a query like this.
SELECT count(*)
FROM table1 e
WHERE e.column1=1
AND e.id IN
(SELECT MAX(ID)
FROM table2 A
WHERE A.column1=1
AND A.date=CURDATE()
GROUP BY A.column2);
When I run this query it is taking too much of time as I am having thousands of records. How can I tune the query to perform better.
Thanks in advance.
EDIT: column2 in table2 is id of Table1
Change in (. . .) To use join instead. Like
SELECT count(*)
FROM table1 AS e
Inner join
(
SELECT MAX(ID)
FROM table2 A
WHERE A.column1 = 1
AND A.date = CURDATE()
GROUP BY A.column2
) t2 on e.id = t2.id
WHERE e.column1 = 1
Maybe:
SELECT count(*)
FROM table1 e
WHERE e.column1=1
AND EXISTS
(SELECT *
FROM table2 A
WHERE A.column1=1
AND A.date=CURDATE()
AND A.ID = e.id);

Complex MySQL query using group by

Lets say i have two tables
Table1:
product_id, design1, design2
1 A C
2 B A
Table2:
product_id, value
1 10
2 10
Now i want to to sum all the value for particular design for all products.
SELECT designA, SUM(value) FROM (
SELECT b.design1 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design1) AS T GROUP BY designA
It gives me this:
designA SUM(value)
A 10
B 10
Now the problem is that if user has specified design2 in table1 then what ever is the value of design1 will automatically be added in design2. If design2 is not present design1 column then it will be a new row of result:
Desited result is this:
designA SUM(value)
A 20
B 10
C 10
select y.designA, sum(value) from
(select a.design1 as designA, value from
Table1 as a
inner join Table2 as b
on
a.product_id = b.product_id
union all
select a.design2 as designA, value from
Table1 as a
inner join Table2 as b
on
a.product_id = b.product_id) as y
group by y.designA
seems to work for your test data, not tried on other configurations but you should be able to tweak it, if you understand what it's doing.
UNION in the matches based on design2:
SELECT designA, SUM(value) FROM (
SELECT b.design1 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design1
UNION
SELECT b.design2 AS designA, SUM(value) AS value FROM table2 AS a LEFT JOIN table1 AS b ON a.product_id = b.product_id GROUP BY b.design2
) AS T GROUP BY designA