MySQL joining table into query which has no refference with others - mysql

I would like to make a query from muliple prestashop tables to be able to import it to another database. The problem is that the third table has no refference to the other two and couldn't figure out how I can join them together.
To simplify things lets say the 3 table looking like this:
Table1 Table2 Table3
ID ID | Table1 ID ID
------ -------------- ------
1 11 | 1 12
2 22 | 1 13
3 44 | 2
55 | 2
66 | 3
77 | 3
And I would like this result:
firstID | secondID | thirdID
1 | 11 | 12
1 | 22 | 12
1 | 11 | 13
1 | 22 | 13
2 | 44 | 12
2 | 55 | 12
2 | 44 | 13
2 | 55 | 13
3 | 66 | 12
3 | 77 | 12
3 | 66 | 13
3 | 77 | 13
Or in words, I would like to assign everery Table3 ID to every Table2 ID and also display Table2's refference to Table1 aka Table1 ID
When I query Table1 and Table2 I usually do it like this:
SELECT p.`id` AS `firstID`, pa.`id` AS `secondID`
FROM `Table1` p
LEFT JOIN `Table2` pa ON (p.`id` = pa.`id`)
GROUP BY pa.`id`
ORDER BY p.`id`
But I wasn't able join the third table in so it would produce the desired outcome.
How can I achieve the above mentioned result?

You are looking for cross join with inner join. Try :
Select
a.ID, b.ID, c.ID
from
Table1 a Inner Join
Table2 b on a.ID = b.Table1_ID
Cross Join
Table3 c
This will fetch table1 and table2 based on ID and table3 will be cross joined with result.
More about cross join can be found here

EDIT: Renamed table ids to match OPs table structures.
SELECT t1.`ID` AS `firstID`, t2.`ID` AS `secondID`, t3.`ID` AS `thirdID`
FROM `Table1` t1
LEFT JOIN `Table2` t2 ON (t1.`ID` = t2.`Table1 ID`)
LEFT JOIN `Table3` t3 ON 1
ORDER BY t1.`ID`, t3.`ID`
This gives same result as you expect.
SELECT t1.`ID` AS `firstID`, t2.`ID` AS `secondID`, t3.`ID` AS `thirdID`
FROM `Table3` t3, `Table1` t1
LEFT JOIN `Table2` t2 ON (t1.`ID` = t2.`Table1 ID`)
ORDER BY t1.`ID`, t3.`ID`

Related

Count records in one table where there are no records in linked table matching certain criteria

I have 2 tables:
T1:
id | name
------ | ------
1 | Bob
2 | John
3 | Joe
T2:
id | T1_id | type
------ | ------ | ------
1 | 1 | call
2 | 1 | email
3 | 1 | fax
4 | 2 | call
5 | 2 | email
6 | 2 | fax
7 | 3 | call
8 | 3 | email
I want to count the number of records in T1 which do not have a record in T2 with a type of 'fax'.
So the answer in this case would be 1 (3|Joe)
Currently I have:
SELECT count(*)
FROM `T1`
JOIN `T2` on `T1`.`id` = `T2`.`T1_id`
WHERE `T2`.`type` != 'fax'
But this is obviously counting all the records which are not 'fax'. I just cant get the logic in my head.
Any help would be appreciated!
A subquery is unnecessary:
SELECT COUNT(DISTINCT t1.id)
FROM t1
LEFT
JOIN t2
ON t2.t1_id = t1.id
AND t2.type = 'fax'
WHERE t2.id IS NULL;
select count(*)
from
(
SELECT t1.id
FROM T1
LEFT JOIN T2 on T1.id = T2.T1_id
GROUP BY t1.id
HAVING sum(T2.type = 'fax') = 0
) tmp
The answers given by Strawberry and juergen d are correct, but for completeness, here's another example using NOT EXISTS. All the queries will have different execution plans, so depending on your data in T1 and T2 YMMV:
SELECT COUNT(*)
FROM `T1`
WHERE NOT EXISTS (
SELECT *
FROM `T2`
WHERE `T2`.`T1_id` = `T1`.`id`
AND `T2`.`type` = 'fax'
)

SQL select 2 tables but not ommit blank results

I have to do a select from 3 trables.
table1- idc,title,description..
table2- idc,filename,filepath,tabel1FK
table3- idc,table1FK,tabel2FK
I need a select from table1 and table2 and count unique ocurrences of table1 in table3
the select must be something like this
TB1 | TB2 | COUNT ON TB3
a | aa | 1
b | | 4
c | cc | 3
d | | 0
e | | 3
I think you just want left join and group by:
select tb1.idc, tb2.idc, count(tb3.idc)
from tb1 left join
tb2
on tb2.table1FK = tb1.idc left join
tb3
on tb3.table1FK = tb1.idc and tb3.tabel2FK = tb2.idc
group by tb1.idc, tb2.idc;

GROUB BY in MySQL JOIN query

There is two table. First one which stores fee per user
+----+----+----+
| id |uid |fee |
+----+----+----+
| 1 |P001|100 |
+----+----+----+
| 2 |P002|200 |
+----+----+----+
| 3 |P003|250 |
+----+----+----+
| 4 |P004|100 |
+----+----+----+
| 5 |P001|200 |
+----+----+----+
| 6 |P002|200 |
+----+----+----+
| 7 |P003|250 |
+----+----+----+
| 8 |P004|100 |
+----+----+----+
second one stores user classification
+----+-----+
|uid |class|
+----+-----+
|P001| 1 |
+----+-----+
|P002| 1 |
+----+-----+
|P003| 2 |
+----+-----+
|P004| 3 |
+----+-----+
I want to show their sum grouped by class as following
1 - 700
2 - 500
3 - 200
How should I write this SQL query? Thanks in advance.
Suppose first table tab1 and second1 is tab2
select t2.class,sum(t1.fee) from tab2 t2 inner join tab1 t1 on t2.uid=t1.uid
group by t2.class
Try this
SELECT a.class, SUM(b.fee)
FROM user_classification a
INNER JOIN user_fees b
ON a.uid = b.uid
GROUP BY a.class
ORDER BY a.class ASC
Try this:
SELECT class, SUM(fee)
FROM table1 t1
LEFT JOIN table2 t2
ON t1.uid = t2.uid
GROUP BY class
SELECT COUNT(*) AS Expr28, SInv_D.fTransUnitPrice AS fTransUnitPrice, SInv_D.fExtended AS Expr2, SInv_D.fTransQty * SInv_D.fTransUnitPrice AS fTransUnitPrice,
SInv.cMode AS cMode, SInv.cInvoicNum AS cInvoicNum, SInv.dOperaDate AS dOperaDate, SInv_D.cMode AS Expr9, SInv_D.cInvoicNum AS Expr10,
SInv_D.cItCode AS cItCode, SInv_D.cItName AS cItName, SInv_D.cTransUnit AS cTransUnit, SUM(SInv_D.fTransQty) AS fTransQty, SInv.cMode AS Expr4,
SInv.cInvoicNum AS Expr16, SInv_D.cItCode AS Expr15, SInv_D.fTransUnitPrice AS Expr19, SInv.dIssueDate AS Expr20, WareDef.cCode AS Expr21,
WareDef.cName1 AS Expr22, item.cUnitR AS Expr24, item.cName1 AS Expr25, item.fCostSTDR AS Expr26, SInv.cWare1 AS Expr27, item.cCode AS cCode, I.Expr999,
I.cItCode AS Expr1
FROM SInv LEFT OUTER JOIN
WareDef ON SInv.cWare1 = WareDef.cCode LEFT OUTER JOIN
SInv_D ON SInv.cInvoicNum = SInv_D.cInvoicNum AND SInv.dIssueDate = SInv_D.dIssueDate LEFT OUTER JOIN
item ON SInv_D.cItCode = item.cCode INNER JOIN
(SELECT SUM(fTransQty) AS Expr999, cItCode
FROM dbo.sinv_D
GROUP BY sinv_D.cItCode) I ON I.cItCode = SInv_D.cItCode
WHERE (SInv.dIssueDate BETWEEN 20130102 AND 20130109) AND (SInv.cWare1 = '003') AND (SInv.cMode = '122') AND (SInv_D.cMode = '122')
GROUP BY SInv_D.cItCode, SInv_D.fTransUnitPrice, SInv_D.fExtended, SInv_D.fTransQty, SInv.cMode, SInv.cInvoicNum, SInv.dOperaDate, SInv_D.cMode, SInv_D.cInvoicNum,
SInv_D.cItName, SInv_D.cTransUnit, SInv.dIssueDate, WareDef.cCode, WareDef.cName1, item.cUnitR, item.cName1, item.fCostSTDR, SInv.cWare1, item.cCode,
I.Expr999, I.cItCode

joining two tables, select values from two with second table having no records

I have two tables where i fetch values from both tables, the situation is the first table always contains records but second table may or maynot.
here are tables
TAB1
id | rank
1 | TL
2 | PL
3 | MG
TAB2
num | id | swiped_on
1 | 1 | 20-4-14
2 | 1 | 21-4-14
3 | 3 | 25-4-14
the result i want is,(only one record from the second table)
id | rank | swiped_on
1 | TL | 21-4-14
2 | PL | -------
3 | MG | 25-4-14
please help
You can use a left join with a subselect from table tab2
select t.*,t1.swiped_on
from TAB1 t
left join (select id , max(swiped_on) swiped_on
from TAB2 group by id
) t1
on(t.id = t1.id)
Fiddle demo
Or just get the max of swiped_on from tab2
select t.*,max(t1.swiped_on) swiped_on
from TAB1 t
left join TAB2 t1
on(t.id = t1.id)
group by t.id
Fiddle demo

Sum Log values from table using second table

I have a huge table where a new row could be an "adjustment" to a previous row.
TableA:
Id | RefId | TransId |Score
----------------------------------
101 | null | 3001 | 10
102 | null | 3002 | 15
103 | null | 3003 | 15
104 | 101 | | -5
105 | null | 3004 | 5
106 | 105 | | -10
107 | null | 3005 | 15
TableB:
TransId | Person
----------------
3001 | Harry
3002 | Draco
3003 | Sarah
3004 | Ron
3005 | Harry
In the table above, Harry was given 10 points in TableA.Id=101, deducted 5 of those points in TableA.Id=104, and then given another 15 points in TableA.Id=107.
What I want to do here, is return all the rows where Harry is the person connected to the score. The problem is that there is no name attached to a row where points are deducted, only to the rows where scores are given (through TableB). However, scores are always deducted from a previously given score, where the original transaction's Id is referred to in the tables as "RefId".
SELECT
SUM TableA.Score
FROM TableA
LEFT JOIN TableB ON TableA.Trans=TableB.TransId
WHERE 1
AND TableB.Person='Harry'
GROUP BY TableA.Score
That only gives me the points given to Harry, not the deducted ones. I would like to get the total scored returned, which would be 20 for Harry. (10-5+15=20)
How do I get MySQL to include the negative scores as well? I feel like it should be possible using the TableA.RefId. Something like "if there is a RefId, get the score from this row, but look at the corresponding TableA.Id for the rest of the data".
Select sum(total) AS total
From tableb
Join
(
Select t1.transid, sum(score) AS total
From tablea t1
Join tablea t2 on t1.id = t2.refid
group by t1.transid
) x on x.transid = tableb.transid
Where TableB.Person='Harry'
try this:
select sum(sum1 + sums) as sum_all from (
SELECT t1.id,T1.Score sum1, coalesce(T2.score,0) sums
FROM Table1 t1
inner JOIN Table2 ON T1.TransId=Table2.TransId
left JOIN Table1 t2 ON t2.RefId = t1.id
WHERE Table2.Person='Harry'
)c
DEMO HERE
OUTput:
SUM_ALL
20
If you assume that adjustments don't modify adjustments, you can do this without aggregating all the data:
select sum(a.score + coalesce(aref.score, 0)) as HarryScore
from tableA a left outer join
tableA aref
on a.refId = aref.id left outer join
tableB b
on a.TransId = b.Transid left outer join
tableB bref
on aref.TransId = bref.TransId
where b.Person = 'Harry' or bref.Person = 'Harry';