How to join where duplicates are needed? - mysql

I have a table structure like this
Table1
PersonID, referrer
Table2
Event_A_ID, PersonID, status
Table3
Event_B_ID, PersonID, status
I want to get the event status for everyone from table one with referrer=X by joining all of the event tables like Event_A...K and checking for PersonID. Since people can appear in multiple events we can have cases like this
PersonID=1001, EventA_ID, referrer=X, status
PersonID=1001, EventB_ID, referrer=X, status
PersonID=1001, EventK_ID, referrer=X, status
PersonID=1002, ...
PersonID=1003, ...
But I am not sure how to JOIN all of the event tables since the IDs can be duplicates (and are desired).
I tried to make a separate select and use the in syntax
...
WHERE 1=1
AND PersonID IN (SELECT PersonID from table1 where referrer=X)
But then I realized everything before will be an aggregate of events.
Should I start with the SELECT from Table1? Select the valid IDs first and then select from the events after? If so, how do I JOIN? I feel like ideal looks like union of all the event tables and then select

You can use union all for row wise implementation of data or you can also use inner joins between tables if there is not much table events. This will represent data in column format.
SELECT * FROM tb2 AS t2 INNER JOIN tb3 t3 ON t2.personId = t3.personId INNER JOIN tb1 t1 ON t1.personId = t2.personId WHERE t1.refer='refer1'
There can be many other approach too depending on the number of tables you want to join.
You should also consider to use a better relations among your db tables as your current scenario will lead you to have as many tables as many events you have. This will create slowness in retrieving the data for multiple events.

use union all and then apply join
select a.person_id,a.referrer,b.eventID,b.PersonID,b.status from Table1 a inner join
(
select Event_A_ID as eventID, PersonID, status from Table2
union all
select Event_B_ID as eventID, PersonID, status from Table3
)b on a.personid=b.personid

You can do something like this with left joins:
SELECT t1.PersonID, t1.referrer,
t2.Event_A_ID, t2.status as status_a,
t3.Event_B_ID, t3.status as status_b
.
.
.
FROM table1 t1
LEFT JOIN table2 t2 ON t2.PersonID = t1.PersonID
LEFT JOIN table3 t3 ON t3.PersonID = t1.PersonID
.
.
.
WHERE t1.referrer = 'x'

Related

SQL Inner Joins Giving Incorrect Count Values in MS ACCESS

I am trying to use join to connect multiple tables in MS Access to get count values. But I don;t know it gives wrong count values. If I try to join them individually, then it gives me correct count values.
I have 3 Tables. Table 2 and Table 3 are independent and are connected to Table 1. Test 2 and test 3 are basically text values and I want to count the rows .
Table1(ID1(Primary Key),Name)
Table2(ID2(Primary Key), ID1(Foreign Key), Test2)
Table3 (ID3(Orimary Key), ID1(Foreign Key), Test3)
The Query that I get from MS Access is given below:
SELECT Table1. ID1, Count(Table2.Test2) AS CountOfTest2, Count(Table3.Test3) AS CountOfTest3
FROM (Table1 INNER JOIN Table2 ON Table1.ID1 = Table2.ID2)
INNER JOIN Table3 ON Table1. ID1 = Table3.ID3
GROUP BY Table1.ID1;
But this gives me wrong Count Values.
Can someone please help me.
Thanks.
When I use it individually, it gives me correct count value:
SELECT Table1. ID1, Count(Table2.Test2) AS CountOfTest2
FROM Table1 INNER JOIN Table2 ON Table1.ID1 = Table2.ID1
GROUP BY Table1.ID1;
SELECT Table1. ID1, Count(Table3.Test3) AS CountOfTest3
FROM Table1 INNER JOIN Table3 ON Table1.ID1 = Table3.ID1
GROUP BY Table1.ID1;
But when I try to join Table1, Table2 and Table 3 in MS Acces, it gives me incorrect count values.
SELECT Table1. ID1, Count(Table2.Test2) AS CountOfTest2, Count(Table3.Test3) AS CountOfTest3 FROM (Table1 INNER JOIN Table2 ON Table1.ID1 = Table2.ID1) INNER JOIN Table3 ON Table1. ID1 = Table3.ID1 GROUP BY Table1.ID1
As per my understanding it is taking the count value of 1st query in the parenthesis and multiplying it with the count values of the other inner join.
I have tried many things but don't know what to do. Access adds parenthesis for some reason.
If I can assume test2 and test 3 are unique to each record (perhaps it would be better to count the PK?)
SELECT Table1.ID1
, Count(distinct Table2.Test2) AS CountOfTest2
, Count(distinct Table3.Test3) AS CountOfTest3
FROM Table1
INNER JOIN Table2
ON Table1.ID1 = Table2.ID2
INNER JOIN Table3
ON Table1.ID1 = Table3.ID3
GROUP BY Table1.ID1;
Or you may have to get the counts before the joins though the use of inline views. You could use window functions if MSSQL SERVER but Access needs the inline views.
SELECT A.ID1
, B.CountOfTest2
, C.CountOfTest3
FROM Table1 A
INNER JOIN (SELECT Table2.ID2, count(table2.test) as CountOfTest2
FROM Table2
GROUP BY Table2.id) B
ON Table1.ID1 = B.ID2
INNER JOIN (SELECT Table3.id, count(table3.test3) as CountOfTest3
FROM Table3
GROUP BY Table3.id) C
ON B.ID1 = C.ID3
GROUP BY A.ID1;
Yup i had the same problem when i was trying to do this. just use the double sql function to counteract the html and you should be good. once the query has been doubled it will react like a C++ quota statement. If this fails you can always just quantify the source fields to adhear to the table restrictions. its actually a piece of cake i hope this helped.

Mysql need to get one column two times from table1 and sort them by two different columns of table2

So here is the thing, I have two tables:
table1 has columns intUsersID, varUsersName
table2 has columns intCouriers, intResponsible
intCouriers (have some numbers of intUsersID that are Couriers), and intResponsible (have some numbers of intUsersID that are Responsible)
In my query I must see User Names of Couriers and of the Responsible persons
something like that:
SELECT
table1.varUsersName 'Couriers',
table1.varUsersName 'Responsible'
FROM
table1
LEFT JOIN
table2 ON table2.intCouriers = table1.intUsersID
And then I need some how to subquery or join this "table1.varUsersName 'Responsible'", to get also 'Reponsible' persons. Please help me.
Should be this
SELECT table1.varUsersName 'Couriers', table2.varUsersName 'Responsible'
FROM table1
INNER JOIN table3 on table1.intUsersID = table3.intCouriers
INNER JOIN table1 as Table2 on table2.intUsersID = table3. intResponsible
SELECT Couriers.varUsersName as "Couriers",
Responsible.varUsersName as "Responsible"
FROM `table2` t2
LEFT JOIN table1 Couriers on Couriers.intUsersID = t2.intCouriers
LEFT JOIN table1 Responsible on Responsible.intUsersID = t2.intResponsible

Why join on subquery is so slow?

Consider following query:
SELECT
...
FROM table1
LEFT JOIN table2 ...
LEFT JOIN table3 ...
LEFT JOIN table4 ...
LEFT JOIN table5 ...
LEFT JOIN
(
SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id
) temp ON temp.id = table1.id
WHERE temp.qty = 123
GROUP BY table1.id
This query is very slow, however when I execute
SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id
alone, it's blazing fast, it returns only few (20-30) rows...
My current solution is a temporary table with index, I fill it with data, then I use join:
DROP TABLE IF EXISTS tmp_counts;
CREATE TABLE tmp_counts id INT(11), qty INT(11) ...
INSERT INTO tmp_counts (id,qty) (SELECT id, COUNT(*) as qty FROM other WHERE ... GROUP BY id);
SELECT
...
FROM table1
LEFT JOIN table2 ...
LEFT JOIN table3 ...
LEFT JOIN table4 ...
LEFT JOIN table5 ...
LEFT JOIN tmp_counts ON tmp_counts.id = table1.id
WHERE tmp_counts.qty = 123
GROUP BY table1.id
It works very fast, but I feel like it's an ugly solution.
Is MySQL really that stupid I need to do mysql job manually by myself?
MySQL isn't that stupid. Optimizing databases is complicated. In fact, when you think about it, there is very little software that does such optimizations across such a large variety of different situations. Procedural and object oriented languages -- they are told what to do. In SQL, we say what we want and let the optimizer figure out the best. What is best, in turn, can depend heavily on the underlying data.
Sometimes the optimizer is wrong. Sometimes we can convince it otherwise. The problem here is quite possibly the choice of join order or join algorithms. One method to get around a problem like this is to replace the subquery with a correlated subquery in the select:
select
SELECT . . .,
(SELECT COUNT(*)
FROM other
WHERE . . . AND
other.id = table1.id
) as qty
...
FROM table1
LEFT JOIN table2 ...
LEFT JOIN table3 ...
LEFT JOIN table4 ...
LEFT JOIN table5 ...
GROUP BY table1.id;
This, in turn, can be further optimized by creating an index on other. At the very least, this would be other.id.

SQL Query To Get All Records From One Table, Except A Specific Record, By Date, From Another Table

I am trying to SELECT records from two MySql tables. I would like all records from the first table excluding specific records, by date, from the second table. For example:
Table1 T1id, firstName, LastName
Table2 id, T1id, hours, rate, date
T1id is the link between the two tables, therefore when the tables are joined I would have T1id, firstName, lastName, hours, rate, date
Let's say there is a record in Table2 with a date of 2012-02-08. With one query, I need to select all records from Table1, excluding the record from Table2 that has the date of 2012-02-08.
I've tried a few variations of JOINS and UNIONS, however I either get all records, a bunch of duplicate records, or one record (i.e. Table2 date). I apologize, but I do not have a specific piece of code to include since nothing has worked for me.
So many times this is typically done with a NOT EXISTS subquery, but subqueries can be big performance hits in larger tables... However, by doing a LEFT JOIN and looking for NULL is in essence, the same result
select
t1.*
from
table1 t1
left join table2 t2
on t1.t2.t1id
AND t2.date = '2012-02-08'
where
t2.t1id IS NULL
USE INNER JOIN if you are sure that T1id exists in both tables:
SELECT a.T1id,
a.FirstName,
a.LastName,
b.hours,
b.rate,
b.date
FROM table1 a INNER JOIN table2 b
ON a.T1id = b.T1id
WHERE b.date <> DATE('2012-02-08')
but if you want to get all T1id from Table1 (which exists or does not exists in Table2) use LEFT JOIN
SELECT a.T1id,
a.FirstName,
a.LastName,
b.hours,
b.rate,
b.date
FROM table1 a LEFT JOIN table2 b
ON a.T1id = b.T1id
WHERE b.date <> DATE('2012-02-08')

How to use INNER/OUTER JOIN in MYSQL

I have 3 tables which contain different types of data related to each other. the tables populate via an excel spreadsheet. I have:
table1 table2 table3
item_number item_number item_number
desc desc qty_sold
qty_instock vdf_cost upc
cost status
What I'm trying to do is use a join function to show all the data as they relate to each other, except the problem is that when I run
SELECT *
FROM table1 a
INNER JOIN table2 b
ON a.someColumn = b.otherColumn
INNER JOIN table3 c
ON b.anotherColumn = c.nextColumn
It just puts the tables side by side, If I run
SELECT *
FROM table1 a
INNER JOIN table2 b
USING(item_number)
It works but only joins the item number (i have no idea how to use multiple fields such as description which repeats), and for some reason I can only use the two tables when I try to add a third table (most likely being done completely wrong)
SELECT *
FROM table1 a
INNER JOIN table2 b
INNER JOIN table3 c
USING(item_number)
I just get a syntax error.
Thanks for all the help in advance
UPDATE:
I got it working
SELECT *
FROM master_list a
INNER JOIN bby_report ab USING (item_number, description)
INNER JOIN sales_report b USING (item_number)
Is there a way I can exclude the description from one of the tables and keep it from another one? Turns out the descriptions are not an exact match from one table to a another so it keeps returning zero results.
So to clarify keep description from table1 and leave out description from table2 while being able to JOIN the fields based on item_number
SELECT *
FROM master_list a
INNER JOIN bby_report ab USING (item_number, description)
INNER JOIN sales_report b USING (item_number)