I'm writing a php code to calculate a value. I have 4 tables with 2 column each. their headers are same. I want to fetch second column of tables that have, say 'MAN', value on their first column:
here are my tables and their dummy values:
I joined tables on 'dst' with a where clause but the problem arises when a table has does not have a common value and we have not full outer join in mysql. I know we can simulate this with union all operation but I want a efficient way to do this.
here is my try:
select t1.dst, t1.pay as pay, t2.pay as pay2, t3.pay as pay3, t4.pay as pay4 from t1 left outer join t2 on t1.dst = t2.dst left outer join t3 on t3.dst=t2.dst left outer join t4 on t1.dst=t4.dst where t1.dst='man';
it's dummy because left outer join is not true for this purpose except special cases.
actually I want this:
First union then pivot
drop table if exists t,t1,t2,t3;
create table t (dst varchar(3),value int);
create table t1 (dst varchar(3),value int);
create table t2 (dst varchar(3),value int);
create table t3 (dst varchar(3),value int);
insert into t values ('abc',10),('man',10);
insert into t1 values ('abc',10),('man',5);
insert into t2 values ('abc',10),('man',10);
insert into t3 values ('abc',10);
select dst,
MAX(CASE WHEN tbl = 't' then value end) as t1,
MAX(CASE WHEN tbl = 't1' then value end) as t1,
MAX(CASE WHEN tbl = 't2' then value end) as t2,
MAX(CASE WHEN tbl = 't3' then value end) as t3
from
(
select 't' as tbl,dst,value from t where dst = 'man'
union
select 't1' as tbl,dst,value from t1 where dst = 'man'
union
select 't2' as tbl,dst,value from t2 where dst = 'man'
union
select 't3' as tbl,dst,value from t3 where dst = 'man'
) s
group by s.dst;
+------+------+------+------+------+
| dst | t1 | t1 | t2 | t3 |
+------+------+------+------+------+
| man | 10 | 5 | 10 | NULL |
+------+------+------+------+------+
1 row in set (0.00 sec)
Related
I have multiple table like this :
I want the result like in the picture if I use 'where table1.id = 1' :
table2 is store value and key of columns name
table3 is store columns name that I need to show
The result should be
ID | Name | A | B | C
1 | a | 10 | 20 | 30
You need little JOINs with conditional aggrgation :
select t1.id, t1.name,
sum(case when t3.name = 'a' then t2.value else 0 end) as A,
sum(case when t3.name = 'b' then t2.value else 0 end) as B,
sum(case when t3.name = 'c' then t2.value else 0 end) as C
from table1 t1 inner join
table2 t2
on t2.table1_id = t1.id inner join
table3 t3
on t3.key_id = t2.key
where t1.id = 1
group by t1.id, t1.name;
However, this would do aggregation with only known values prior, if you want go with dynamic way, then you might need programming approach in MySQL.
I have to tables with users. Both have one mail column and one mobile column. I have to find all rows in table1 where both mail and mobile is not in table2. And mail and mobile is not empty in table1.
The object is to find users from table1 that doesn't yet exist in table2. And we use mail or mobile to identify them.
I use MySQL
table1
|mail |mobile |
|a#mail.com |12345678|
| |21345678|
|c#mail.com |84726287|
table2
|mail |mobile |
|d#mail.com |12345678|
|q#mail.com |21888888|
|c#mail.com | |
Result
|a#mail.com |12345678|
| |21345678|
If you want to find users where there is no mail and no mobile in the other table:
SELECT t1.*
FROM dbo.Table1 t1
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Table2 t2
WHERE t1.Mail = t2.Mail
)
AND NOT EXISTS
(
SELECT 1
FROM dbo.Table2 t2
WHERE t1.Mobile = t2.Mobile
)
If both must match on the same row it's simpler:
SELECT t1.*
FROM dbo.Table1 t1
WHERE NOT EXISTS
(
SELECT 1
FROM dbo.Table2 t2
WHERE t1.Mail = t2.Mail AND t1.Mobile = t2.Mobile
)
select a.mail, a.mobile
from table1 a
left outer join table2 b on a.mail = b.mail and a.mobile = b.mobile
where b.mail is null
and a.mail <> ''
and a.mobile <> ''
I have this table
Table1
id | name |
1 | a |
2 | c |
and other table like this
Table2
id | name |
1 | b |
2 | d |
How can I sort this two table to result
a b c d
DONE READING THIS but it will only gives me this result
a c b d
when I try this
SELECT * FROM Table1 AS t1 JOIN Table2 AS t2 ON t2.id = t1.id
ORDER BY t1.name ASC, t2.name ASC;
You can try taking a UNION of the two tables instead:
SELECT id, name
FROM Table1
UNION ALL
SELECT id, name
FROM Table2
ORDER BY name
If you want to retain information about the original source of each record, you can add a column for that:
SELECT id, name, 't1' AS source
FROM Table1
UNION ALL
SELECT id, name, 't2'
FROM Table2
ORDER BY name
Update:
If Codeigniter does not support UNION out of the box, you can always put the above query into a string and execute it natively:
$sql = "SELECT id, name FROM Table1 UNION ALL SELECT id, name FROM Table2 ORDER BY name";
$this->db->query($sql);
SELECT *
INTO #TEMP_TBL
FROM Table1 AS t1
JOIN Table2 AS t2
ON t2.id = t1.id
SELECT *
FROM #TEMP_TBL
ORDER BY ID, NAME
DROP TABLE #TEMP_TBL
If you want to use join then try below query
select * from (select x.* from table1 as x left join table2 as y on x.id = y.id) as z order by z.name;
We can use this also:
SELECT * FROM (
SELECT id, NAME FROM Table1
UNION ALL
SELECT id, NAME FROM Table2) t ORDER BY name
I have a table which uses external data that arrives cut off. Can I complete it from tables that aren't cut off (as they use alternative external data)?
In this example, the 2nd and 3rd rows can be completed using the matching data from their respective tables.
Table1:
Table | Type | Description
X | A | A long line th
X | B | A long line th
Y | B | This line d
Y | A | This line d
TableX:
Type | Description
A | A very long line that doesn't get cut off
B | A long line that doesn't get cut off
TableY:
Type | Description
A | just a long line that doesn't get cut off
B | This line doesn't get cut off
Needed result
===============
Table1:
Project | Type | Description
X | A | A long line th
X | B | A long line that doesn't get cut off
Y | B | This line doesn't get cut off
Y | A | This line d
try something like this...
SELECT `Table` as Project,Type,Description
FROM Table1 T1 WHERE Type = 'A'
UNION ALL
SELECT `Table`,T1.Type,T2.Description
FROM Table1 T1 INNER JOIN TableX T2
ON T1.`Table` = 'X' AND T1.Type = 'B' AND T1.Type = T2.Type
UNION ALL
SELECT `Table`,T1.Type,T2.Description
FROM Table1 T1 INNER JOIN TableY T2
ON T1.`Table` = 'Y' AND T1.Type = 'B' AND T1.Type = T2.Type
http://www.sqlfiddle.com/#!9/b40a3/6
SELECT `Table` as Project,Type,Description
FROM Table1 T1 WHERE Type = 'A'
UNION ALL
SELECT `Table`,T1.Type,T2.Description
FROM Table1 T1 INNER JOIN TableX T2
ON T1.`Table` = 'X' AND T1.Type = 'B' AND T1.Type = T2.Type
AND T2.Description like CONCAT(T1.Description,"%")
UNION ALL
SELECT `Table`,T1.Type,T2.Description
FROM Table1 T1 INNER JOIN TableY T2
ON T1.`Table` = 'Y' AND T1.Type = 'B' AND T1.Type = T2.Type
AND T2.Description like CONCAT(T1.Description,"%")
If you're trying to match description too you can use something like
http://www.sqlfiddle.com/#!9/b40a3/9
To complete rows you can select and update Description.
update Table1 set Description = (select Description from TableX where Description LIKE 'A long line th%' limit 1);
update Table1 set Description = (select Description from TableY where Description LIKE 'This line d%' limit 1);
To select without update table you can
select tb1.Table as Proyect, tb1.Type, (select Description from TableX where Description like CONCAT(tb1.Description,'%')) from Table1 tb1 where tb1.Table = 'X'
UNION
select tb1.Table as Proyect, tb1.Type, (select Description from TableY where Description like CONCAT(tb1.Description,'%')) from Table1 tb1 where tb1.Table = 'Y';
And this maybe can help someone,
INSERT INTO Table1 (
select 'X' as Project, Type, Description from Table1
UNION
select 'Y' as Project, Type, Description from Table2);
Maybe your Table1.Description is wrong.
ALTER TABLE Table1 MODIFY COLUMN Description varchar(200);
As a follow up to In SQL / MySQL, what is the difference between "ON" and "WHERE" in a join statement? and SQL join: where clause vs. on clause - it does matter if a condition is placed in the on-clause vs. the where-clause in an outer join.
However, does it matter which on-clause the condition is placed in when there are multiple outer joins?
For example, could these produce different results?
select * from t1 left join t2 on t1.fid=t2.id and t2.col=val
left join t3 on t2.fid=t3.id;
vs:
select * from t1 left join t2 on t1.fid=t2.id
left join t3 on t2.fid=t3.id and t2.col=val;
Absolutely they are different.
The fisrt query will only have t2 rows that satisfy t2.col=val
The second query will include all t2 rows and only list t3 when t2.col=val
The queries are not equivalent. It is easy to construct a counter example:
create table t1 (id int not null, val int not null);
create table t2 (id int not null, val int not null);
create table t3 (id int not null, val int not null);
insert into t1 (id, val) values (1,1);
insert into t2 (id, val) values (1,1);
insert into t3 (id, val) values (1,1);
select * from t1
left join t2
on t1.id = t2.id
and t2.val = 2
left join t3
on t2.id = t3.id;
+----+-----+------+------+------+------+
| id | val | id | val | id | val |
+----+-----+------+------+------+------+
| 1 | 1 | NULL | NULL | NULL | NULL |
+----+-----+------+------+------+------+
select * from t1
left join t2
on t1.id = t2.id
left join t3
on t2.id = t3.id
and t2.val = 2;
+----+-----+------+------+------+------+
| id | val | id | val | id | val |
+----+-----+------+------+------+------+
| 1 | 1 | 1 | 1 | NULL | NULL |
+----+-----+------+------+------+------+
This is one of the queries:
select *
from t1 left join
t2
on t1.fid = t2.id left join
t3
on t2.fid = t3.id and t2.col = val;
Yes, the results are different. If you were using inner join they would be the same, but the left join changes things -- because the join clause does not do any filtering of rows.
I think the simplest explanation is that the join between t1 and t2 will include all rows from t1 as well as all matching rows from t2 -- even those where t2.col <> val. These remain in the result set, because the next left join does not filter them out.
In fact, the condition t2.col = val in the second on clause does not affect which rows are in the result set. If there is a match, then the row from t3 stays based on the first condition. If there is no match, then the row from t3 is still in the result set -- but the t3 columns will be NULL.
In this version:
select *
from t1 left join
t2
on t1.fid = t2.id and t2.col = val left join
t3
on t2.fid = t3.id;
The first join gets all rows from t1 and only matching rows from t2 where t2.col = val. The third join can then add more rows.
Note: there are definitely situations where the two queries would return the same results. But, the following data would generate different results (assume val = 0):
t1
fid
1
t2
fid col
1 0
1 1
t3
id
1
The query with the condition in the second on clause will return:
1 1 0 1
1 1 1 NULL
The query with the condition in the first on clause will return:
1 1 0 1