I have 2 tables
Table1
Year,Month, data
2017,1,2
2018,2,10
Table2
Year,Month,data2
2017,1,5
2019,2,2
I am trying to consolidate the tables into 1 tables where we get all rows from both tables as follows.
Year,Month,data,data2
2017 ,1,2,5
2018,2,10,NULL
2019,2,NULL,2
It seems like standard outer joins will not work here and I can't use Union ALL either
Is there some kind of Outer join query to accomplish this?
You should use a UNION for obtain allthe year and month from both tables and use left join for relate this to table1 and table2
select a.Year , a.Month, b.data, c.data2
from (
select Year,Month
from Table1
union
select Year,Month
from Table2
) a
left join table1 b on a.Year = b.Year and a.month = b. month
left join table2 c on a.Year = c.Year and a.month = c. month
What you really want is a full join. One method that often works is union all and group by:
select year, month, max(data) as data, max(data2) as data2
from ((select year, month, data, null as data2
from table1
) union all
(select year, month, null, data2
from table2
)
) t
group by year, month;
Related
I'm having trouble joining two tables that come from two queries, meaning I don't have the actual table in my database. I have the following:
SELECT
fiscalYear,
BidOwner,
count(cbid) AS c
FROM
financials_tbl
GROUP BY
BidOwner,
fiscalYear
that one brings each BidOwner for each year with the amounts of bids he/she did that year.
Now this one:
SELECT
fiscalYear,
max(c)
FROM
(
SELECT
fiscalYear,
BidOwner,
count(cbid) AS c
FROM
financials_tbl
GROUP BY
BidOwner,
fiscalYear
) InputTable
GROUP BY
fiscalYear
brings the maximum amount of bids done by an employee that year (2 columns).
What I need is to join this last table with the corresponding bid owner from the previous one, like a vlookup to find who scored the max amount of deals each year shown in the second table.
It looks like you are trying to find a groupwise maximum on the result of your count query. Unfortunately, I do not know a way to do this without creating two of the same subquery, but I think this should work.
SELECT
t1.fiscalYear, t1.BidOwner, t1.c
FROM
(SELECT fiscalYear, BidOwner, count(cbid) AS c
FROM financials_tbl
GROUP BY BidOwner, fiscalYear) t1
LEFT JOIN
(SELECT fiscalYear, BidOwner, count(cbid) AS c
FROM financials_tbl
GROUP BY BidOwner, fiscalYear) t2
ON t1.fiscalYear = t2.fiscalYear AND t1.c < t2.c
WHERE t2.BidOwner IS NULL
You can join the results in such way:
SELECT
t2.fiscalYear,
t2.BidOwner,
t2.c
FROM (
SELECT
fiscalYear,
max(c) as max
FROM
(
SELECT
fiscalYear,
BidOwner,
count(cbid) AS c
FROM
financials_tbl
GROUP BY
BidOwner,
fiscalYear
) InputTable
GROUP BY
fiscalYear
) t1
JOIN (
SELECT
fiscalYear,
BidOwner,
count(cbid) AS c
FROM
financials_tbl
GROUP BY
BidOwner,
fiscalYear
) t2
ON t2.max = t1.c
AND t2.fiscalYear = t1.fiscalYear;
However performance of such query will not be nice for large data sets...
SELECT a.*, IF(b.pid=a.id,b.id,0) AS bpid
FROM table1 a, table2 b
ORDER BY a.datetime DESC;
I have fifteen records in table1 a, and two records in table2 b where b.pid=a.id.
Only one of those records from table b is being pulled into the result at any given time. Both should be pulled in as bpid, but only the latter of the two makes the trip.
I've also tried using CASE (tried CASE first, actually):
SELECT a.*, (CASE WHEN b.pid=a.id THEN b.id ELSE NULL END) AS bpid
FROM table1 a, table2 b
ORDER BY a.datetime DESC;
What am I missing?
For clarity: I get all 15 records from table1 a in the result, but not both records from table2 b.
You are not joining the tables correctly. As a tip just stop using commas in the FROM clause, this will help make you consider what the joins should be.
/* for all records */
SELECT
a.*
, b.id AS bpid
FROM table1 a
LEFT JOIN table2 b ON a.id = b.id
ORDER BY a.DATETIME DESC
or
/* for only matching records */
SELECT
a.*
, b.id AS bpid
FROM table1 a
INNER JOIN table2 b ON a.id = b.id
ORDER BY a.DATETIME DESC
I have this query that will work if there is data in both tables
SELECT a.location, b.location, a.refno, b.note
FROM (
SELECT location, refno
FROM tableA WHERE refno = '1234'
) a, (
SELECT location, note FROM tableB WHERE note = LN1234567
) b
but some of the time there may not be data in either one of the tables for the specific match in the WHERE clauses
I've also tried this which does work but i need the data on one row
SELECT location, refno
FROM tableA
WHERE refno = '1234'
UNION
SELECT location, note
FROM tableB
WHERE note = 'LN1234567'
My question is, is there an alternative way of querying both tables so I get one row with data from either OR both tables?
You can try with:
SELECT MAX(location_a) AS location_a,
MAX(refno_a) AS refno_a,
MAX(location_b) AS location_b,
MAX(refno_b) AS refno_b
FROM (
SELECT location AS location_a,
refno AS refno_a,
NULL AS location_b,
NULL AS refno_b
FROM tableA
WHERE refno = '1234'
UNION ALL
SELECT NULL AS location_a,
NULL AS refno_a,
location AS location_b,
location AS refno_b
FROM tableB
WHERE note = 'LN1234567') s
Assuming you want matching locations on both side, you want a left join. Here is a simplified version:
SELECT a.location, b.location, a.refno, b.note
FROM tableA a LEFT JOIN
tableB b
on a.location = b.location
WHERE a.refno = '1234' and b.note = 'LN1234567';
If you actually want a cross join (different locations on the same row) and still want results, I think you need a union all:
SELECT a.location, b.location, a.refno, b.note
FROM tableA a CROSS JOIN
tableB b
WHERE a.refno = '1234' and b.note = 'LN1234567'
UNION ALL
SELECT a.location, NULL, a.refno, NULL
FROM tableA
WHERE NOT EXISTS (SELECT 1 FROM tableB b WHERE b.note = 'LN1234567');
Table column headers: n,t1,t2
entries :
1 A B
2 A C
3 B C
4 D E
5 B A
How do I count total number of rows each letter appears in t1 MINUS the number of rows they appear in t2 ? I need to do something like following 2 lines in 1 query :
select count(*) as val,t1 from table group by t1
select count(*) as val,t2 from table group by t2
Thanks,
Martin
Here is one way:
select t1, max(t1cnt) - max(t2cnt) as diff
from ((select t1, count(*) as t1cnt, 0 as t2cnt
from t
group by t1
) union all
(select t2, 0 as t1cnt, count(*) as t2cnt
from t
group by t2
)
) t
group by t1
Using the union all ensures that you get all possible values from both columns, even values that only appear in one column.
You can use the following query to get the result. This query first gets a list of all the distinct t1 and t2 values (this is the UNION query). Once you have the list of these values, then you can use a LEFT JOIN to the original queries that you posted:
select d.col, coalesce(totT1, 0) - coalesce(totT2, 0) Total
from
(
select t1 col
from entries
union
select t2 col
from entries
) d
left join
(
select count(*) totT1, t1
from entries
group by t1
) d1
on d.col = d1.t1
left join
(
select count(*) totT2, t2
from entries
group by t2
) d2
on d.col = d2.t2;
See SQL Fiddle with Demo
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