Looking for away to join 2 tables and keeping all records from the left. The problem is that one of the on statement does not exist in the the other table
Example
Table1 ID, ClassID, Date, Amount
Table2 ID, CLassID, Date, Score
Example statement
select
Table1.ID,
Table1.ClassID,
Table1.Date,
Table1.Amount,
Table2.Score
from Table1
left join Table2 on Table2.ID = Table1.ID
and Table2.ClassID = Table1.ClassID
and Table2.Date = Table1.Date
The Problem is Table1 has an ClassID that Table2 does not have and it is excluding that from the results. If I removed the ClassID as a qualification, I get a ton of duplicates
Your missing value will be null for Score so you will have to deal with that however you like, but this will do the job.
select
Table1.ID,
Table1.ClassID,
Table1.Date,
Table1.Amount,
( SELECT Score
FROM Table2
WHERE ID = Table1.ID
and ClassID = Table1.ClassID
and Date = Table1.Date ) AS 'Score'
from Table1
Related
I have the following sql situation
Table1
id name
Table2
id name
_Table1ToTable2
id, id_table1, id_table2
Result:
id, name, table2_name, table2_id
I would like to join Table1 and Table2 into a single query, but I cannot find a way to make a join between them, any ideas?
It seems like you want to use bridge table Table1ToTable2 to join Table1 and Table2. This can be done simply with 2 INNER JOINs :
SELECT
tt.id AS tt_id,
t1.id AS t1_id,
t1.name AS t1_name,
t2.id AS t2_id,
t2.name AS t2_name
FROM
Table1ToTable2 AS tt
INNER JOIN Table1 AS t1
ON t1.id = tt.id_table1
INNER JOIN Table2 AS t2
ON t2.id = tt.id_table2
if there is no relationship between table1 and table 2 then,
select table1.id, table1.name, table2.id, table2.name from
table1, table2
if table1 and table2 are related with ID then,
select table1.id, table1.name, table2.id, table2.name from
table1
inner join table2
on table1.id = table2.id
If your intention is to retrieve a result set with every possible combination of the id columns from both tables then you can do as follows:
select id = identity (int, 1, 1), * into #a from (select distinct table1. id as id1, table2. id as id2 from table1 cross apply table2) d; select * from #a; drop table #a
If you do not wish to use a temp table an alternative would be to use some variation of the row_number() function.
The above solves for an assumed requirement as your question lacks context. Elaborate on your requirements and we will be able to provide you with a more relevant and detailed answer.
I read few articles about this: Select max date, then max time This one seems most helpful but I do not see way to implement it.
There is five tables. I join them. I need to select only one row with highest date and highest time from first table and same from second table and join the rest on some other value. With the code I wrote I get multiple rows. It seems time selection is not right.
It might be done with subquery in subquery. I've tried something like this:
SELECT * from table1
INNER JOIN table2 ON table1.date = table2.date AND table1.gm = table2.gm
INNER JOIN table3 ON table2.gm = table3.gm ...
WHERE table3.date = :date AND table4.date = :date ...
AND table1.date IN(
SELECT MAX(table1.date) FROM table1 WHERE table1.time IN(
SELECT MAX(table1.time) FROM table1
)
)
AND table2.date IN(
SELECT MAX(table2.date) FROM table1 WHERE table2.time IN(
SELECT MAX(table2.time) FROM table2 )
)
ORDER BY table1.id
Question is:
How to get single row after joining all of this where date is highest and time is highest on that date?
Thanks!
EDIT: I am sorry for this. I forgot to say that I need max time of max date related with specific value from tables(gm columns). So that is one row(in example I gave it is table1.gm and table2.gm ... ) for each one of that .gm values which are same in every table, not just one row all together. Solutions Nick and Salim provided works but I did not solved problem.
EDIT: SOLVED! after implementing solutions by Nick I just neded to add GROUP BY cntrs_reper.gm_company_no, cntrs_reper.date.
And that's it. For every row in one table enties with highest date and time from others!! Thanks to all.
EDIT. If this can help this is full query:
SELECT cntrs_gm.gm_company_no AS company_c_g,
bns_gms.ded_bns AS ded_bns_gms,
bns_gms.no_ded_bns AS no_ded_bns_gms,
bns_gms.wag_ded_bns AS wag_ded_bns_gms,
cntrs_gm.cur_credit AS cur_credit_c_g,
cntrs_gm.cdrop AS cdrop_c_g,
cntrs_gm.total_jp AS total_jp_c_g,
cntrs_gm.games AS games_c_g,
cntrs_gm.wgames AS wgames_c_g,
cntrs_gm.doors AS doors_c_g,
cntrs_gm.power AS power_c_g,
cntrs_gm.total_in AS total_in_c_g,
cntrs_gm.total_out AS total_out_c_g,
cntrs_gm.total_acc AS total_acc_c_g,
cntrs_gm.total_bet AS total_bet_c_g,
cntrs_gm.total_win AS total_win_c_g,
cntrs_gm.total_bonus AS total_bonus_c_g,
cntrs_gm.date AS date_c_g,
cntrs_reper.gm_company_no AS company_reper,
bns_reper.ded_bns AS ded_bns_reper,
bns_reper.no_ded_bns AS no_ded_bns_reper,
bns_reper.wag_ded_bns AS wag_ded_bns_reper,
cntrs_reper.cur_credit AS cur_credit_reper,
cntrs_reper.cdrop AS cdrop_reper,
cntrs_reper.total_jp AS total_jp_reper,
cntrs_reper.games AS games_reper,
cntrs_reper.wgames AS wgames_reper,
cntrs_reper.doors AS doors_reper,
cntrs_reper.power AS power_reper,
cntrs_reper.total_in AS total_in_reper,
cntrs_reper.total_out AS total_out_reper,
cntrs_reper.total_acc AS total_acc_reper,
cntrs_reper.total_bet AS total_bet_reper,
cntrs_reper.total_win AS total_win_reper,
cntrs_reper.total_bonus AS total_bonus_reper,
cntrs_reper.date AS date_reper,
cntrs_reper.time AS time_reper,
bns_reper.time AS time_c_g,
gms_cfg.gm_no AS machine_id,
gms_cfg.denom_cin AS machine_cin
FROM bns_gms
INNER JOIN cntrs_gm
ON bns_gms.gm_company_no = cntrs_gm.gm_company_no AND bns_gms.date = cntrs_gm.date
INNER JOIN bns_reper
ON cntrs_gm.gm_company_no = bns_reper.gm_company_no
INNER JOIN cntrs_reper
ON bns_reper.gm_company_no = cntrs_reper.gm_company_no AND bns_reper.date = cntrs_reper.date
INNER JOIN gms_cfg
ON cntrs_reper.gm_company_no = gms_cfg.gm_no
WHERE bns_reper.date IN(
SELECT MAX(DATE(bns_reper.date)) FROM bns_reper WHERE bns_reper.time IN(
SELECT MAX(TIME(bns_reper.time)) FROM bns_reper
)
)
AND cntrs_reper.date IN(
SELECT MAX(DATE(cntrs_reper.date)) FROM cntrs_reper WHERE cntrs_reper.time IN(
SELECT MAX(TIME(cntrs_reper.time)) FROM cntrs_reper
)
)
ORDER BY cntrs_gm.gm_company_no
DB example
bns_gms
bns_reper
cntrs_gm
cntrs_reper
gms_cfg
The problem with your current query is that it will select all rows where table1.date is the latest date on which the highest time occurs, which may well be more than one e.g. for data such as
id date time
1 2018-03-30 18:40
2 2018-03-31 12:20
3 2018-03-31 19:20
Your WHERE clause:
table1.date IN(
SELECT MAX(table1.date) FROM table1 WHERE table1.time IN(
SELECT MAX(table1.time) FROM table1
)
will select rows with id=2 and id=3 as they both have date = '2018-03-31' which is when the maximum time occurs.
What you want to do is select the row which has the latest time on the latest date, for which you could use
table1.date = (SELECT MAX(date) FROM table1) AND
table1.time = (SELECT MAX(time) FROM table1 WHERE date = (SELECT(MAX(date) FROM table1))
By using aliasing, that can be simplified (since we already know table1.date = MAX(date) FROM table1) to
table1.date = (SELECT MAX(date) FROM table1) AND
table1.time = (SELECT MAX(time) FROM table1 AS t1 WHERE t1.date = table1.date)
I don't have MySQL but here is the general idea you can use. I don't have enough points to write a comment so I am responding as a reply. Essentially make a subquery/inline view for each table to select max of a column, then join those subqueries/inline views together.
Here is Oracle syntax. You can convert it to ANSI syntax.
select table1.column1, table2.column2,table3.column3
from
(select id1, max(column1) as column1 from table1 group by id1) as table1
(select id2, max(column2) as column2 from table2 group by id2) as table2
(select id3, max(column3) as column3 from table3 group by id3) as table3
where
table1.id1 = table2.id2
and table1.id1 = table3.id3
;
The result of this query gives me 0 rows where it should give me the 3 latest rows (grouped by Table1.Name).
Table1 has: "Name", "Timestamp", "Voltage".
Table2 has: "Name", "data".
When I delete "ORDER BY Table1.Timestamp" I do get 3 rows (as expected) but they are the 3 oldest entries in the database where I want the 3 latest.
(I have 3 Name values in Table1 and Table2 that match).
The code:
SELECT * from Table1
INNER JOIN Table2
ON Table1.Name=Table2.Name
GROUP BY Table1.Name
ORDER BY Table1.Timestamp;
You can try to perform a query like this :
SELECT t.*,t2.* from Table1 t
INNER JOIN Table2 t2
ON t.Name=t2.Name
WHERE t.Timestamp = (
SELECT MAX(t3.Timestamp) FROM Table1 t3
WHERE t3.Name = t.Name
)
You could sort and taking the top 3:
SELECT * from Table1
INNER JOIN Table2
ON Table1.Name=Table2.Name
ORDER BY Table1.Timestamp DESC
LIMIT 3
When you are using join two or more tables then don't use * in select query. Use specific column name to avoid column ambiguously in select query , you can also use Table1., Table2. but good way to use specific columns in select query.
SELECT Table1.Name,Table1.Timestamp from Table1
INNER JOIN Table2
ON Table1.Name=Table2.Name
GROUP BY Table1.Name
ORDER BY Table1.Timestamp;
I have two tables with a one-to-many relationship.
Table1
ID name email
Table2
ID table1_ID date
I need to get all the data from Table1 where :
MAX(date) from Table2 < "2016-01-01"
This doesn't work. Max is considered as "invalid" in where clause. What I did was :
SELECT Table1.name, Table1.email, tmp.maxdate
FROM Table1
JOIN ( SELECT MAX(date) maxdate, table1_ID
FROM Table2
GROUP BY table1_ID ) as tmp
ON tmp.table1_ID = table1.id
WHERE tmp.maxdate < "2016-01-01"
AND (other conditions)
So this works. BUT I think the performance is going to be awful - explain shows that all the Table2 is being read, and this table will grow a lot.
Any idea on how I could do it otherwise, or how to improve my current query performances ?
Try:
SELECT Table1.name, Table1.email, tmp.maxdate
FROM Table1
INNER JOIN ( SELECT MAX(date) maxdate, table1_ID
FROM Table2
GROUP BY table1_ID
HAVING maxdate > "2016-01-01" ) as tmp
ON tmp.table1_ID = table1.id
WHERE
AND (other conditions)
Before, you just bringing back everyone from Table2 and join it with Table1. This will knock off all those without the maxdate > "2016-01-01" and do join on it with Table1.
First of all, don't think , test it by your self and check it.
Secondly, you can try using EXISTS() which might be slightly faster becuase you can filter Table2 and not use a GROUP BY clause :
SELECT * FROM Table1 t1
WHERE EXISTS(SELECT 1 FROM Table2 t2
WHERE t2.date > "2016-01-01"
AND t1.id = t2.table1_id
AND <Other Conditions>)
You can also add table2.date > "2016-01-01" inside your sub query.
In addition, consider adding the following indexes:
Table1(id,name,email)
Table2(table1_id,date)
Note that I recommend these indexes based on the query you provided, if there are extra conditions this indexes might not be complete.
I have a database with many tables.. and each table has stored only IDs. Now what I want to do is:
SELECT id FROM table1, table2, table3
GROUP BY id;
but I also want to sort them by decreasing order of occurrence.
For example the IDs that are in all 3 tables should appear on top and the IDs appearing in only one table should be at the bottom. Any clue on how to do this?
Try this too
select id from
(
SELECT id FROM table1
union all
select id from table2
union all
select id from table3
) as t
GROUP BY id
order by count(id) desc
select sum(t1.id IS NOT NULL,t2.id IS NOT NULL, t3.id IS NOT NULL) as total,t1.id from table1 as t1 join table2 as t2 on t1.id=t2.id join table3 as t3 on t3.id = t1.id order by total desc;
I am not sure about your problem but this can help
select id from
(
SELECT id FROM table1
union all
select id from table2
union all
select id from table3
) as t
GROUP BY id
order by id desc