SQL Join 2 tables with "ON" on max value in second table - mysql

I have 2 tables one with inventory and other with prices list on different dates. I need to update table 1 with price on a particular date which may not be available in table 2 so i need to lookback on last available price. How can I do this. Following are my tables:
Table1
SrNo Commodity Date Price
1 Car 20-Aug-2015 <115>
2 Cycle 20-Aug-2015 <78>
Table2
SrNo Commodity Price Date
1 Car 100 1-Jan-2015
2 Car 120 1-Jun-2015
3 Car 115 20-Aug-2015
4 Cycle 80 10-May-2015
5 Cycle 78 10-Jun-2015
I tried using an inner join but I could get it for Car since it has an entry on 20-Aug-2015. I want cycle to be shown as 78 as it was the last available price.
Can someone suggest me how to do this.
Thanks,
Swati

Next code will work on T-SQL - try so
update t1 set
t1.Price = t2.Price
from Table1 as t1
outer apply (
select top 1
t2.Price
from Table2 as t2
where t2.SrNo = t1.SrNo
order by t2.Date desc
) t2

Try this:
UPDATE a
SET a.Price = b.Price
FROM Table1 a
INNER JOIN Table2 b ON a.Commodity = b.Commodity
WHERE b.[Date] = (SELECT MAX([Date])
FROM Table2 c
WHERE b.Commodity = c.Commodity
AND c.[Date] <= a.[Date]
GROUP BY c.Commodity)

For MySql
UPDATE Table1
JOIN ( SELECT Commodity,Price
FROM Table2 JOIN (SELECT Table2.Commodity,MAX(DATE) As LastDate
FROM Table2
GROUP BY Commodity ) AS Tmp1
ON Table2.Date = Tmp1.LastDate
) AS Tmp2
ON Tmp2.Commodity = Table1.Commodity
SET Table1 .Price = Tmp2.Price
MAX(DATE) is calculated in inner query Tmp1 to get last availaible price of commodity
SQLFiddle Demo

Related

mysql group by return all the rows

I have two tables (table 1 and table 2). Table 1 consists the options and table 2 consists the result for each options.
**table1** table2
id id
optionvalue optionvalueid
time (unixtime)
So when the data is inserted it will be stored in table2. There are 5 optionvalue in table 1 and when data is inserted, then in the table2 it will insert the optionvalueid of table 1 and timestamp in unixtimestamp. Eaach month, I want to count the number of values for each optionvalue. Evene if there is no value for an optionvalue, I still want to see count as zero.
I did the following query but only return the value with rows with data only.
SELECT
po.id,po.optionvalue, COUNT(pr.optionvalueid) as votes,
FROM_UNIXTIME(`time`, '%m-%Y') as ndate
FROM table 1
LEFT JOIN table 2 pr ON po.id=pr.optionvalueid
GROUP BY ndate, po.optionvalue ORDER BY ndate ASC
Is there any other ways to make the query so that it will return all the options even if there is no value.
You can CROSS join table1 to the distinct months of table2 and then LEFT join to table2 to aggregate:
SELECT t.ndate, t1.id, t1.optionvalue, COUNT(t2.optionvalueid) votes
FROM table1 t1
CROSS JOIN (SELECT DISTINCT FROM_UNIXTIME(`time`, '%m-%Y') ndate FROM table2) t
LEFT JOIN table2 t2 ON t1.id = t2.optionvalueid AND t.ndate = FROM_UNIXTIME(t2.`time`, '%m-%Y')
GROUP BY t.ndate, t1.id, t1.optionvalue
ORDER BY t.ndate ASC

How to SELECT date and time within that date?

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
;

need help on join query condtion

I am not much in db queries and I require some help on following .
I have two table structures as follow as
table1 :
Name Id1 Id2
Jack 1 1
Jack 1 1
Jack 1 1
table2 :
Name Id1 Id2
Jack 1 1
I used basic join query :
select *
from table1 tb1
join table2 tb2 on tb1.id1 = tb2.id1
and tb2.id2 = tb2.id2
output I get :
Jack 1 1
Jack 1 1
Jack 1 1
But I required following output:
Jack 1 1
Note: I like to show what records is available in table 2 when it combined together!!.. I would like to fetch data with respect table2 only
Thanks in advance.
Please try the following (does not uses aliases) ...
SELECT table2.Name,
table2.Id1,
table2.Id2
FROM table1
JOIN table2 ON table1.id1 = table2.id1 AND
table1.id2 = table2.id2
GROUP BY table2.id1,
table2.id2;
Or try the following (does use aliases)...
SELECT tb2.Name,
tb2.Id1,
tb2.Id2
FROM table1 tb1
JOIN table2 tb2 ON tb1.id1 = tb2.id1 AND
tb1.id2 = tb2.id2
GROUP BY tb2.id1,
tb2.id2;
By performing an INNER JOIN on table2 with table1 on those key fields you are limiting the output to only those rows from table1 that match Id1 and Id2 in table2 (Note : Where JOIN is not preceded by a JOIN type an INNER JOIN is performed). Since multiple rows in table1 meet this criteria you can limit your results to just one row for each matching set of criteria using GROUP BY
This should change the supplied actual query to...
SELECT delta.input_name,
delta.mtcn,
delta.at‌​tempt_id
FROM compliance.rtra_transactions rtra_txn
JOIN compliance.GNR_TEST_RUNS delta ON rtra_txn.mtcn_nr = delta.mtcn
AND rtra_txn.attemptid = delta.attempt_id
WHERE rtra_txn.year = 2017
AND rtra_txn.month = 2
AND rtra_txn.day = 17
AND rtra_txn.trns_ts BETWEEN '2017-02-17 00:00:00' AND '2017-02-17 23:59:00'
AND delta.MATCH_OUTCOME = 'MATCH'
AND delta.job_name = 'Feb17_Run_1'
AND rtra_txn.txn_map[ 'TRANSACTIONTYPE' ] IN ( '10', '7' )
GROUP BY delta.mtcn,
delta.attempt_id;
If you have any questions or comments, then please feel free to post a Comment accordingly.
Following query should work :
SELECT * FROM TBL2 T2
UNION
SELECT * FROM TBL1 T1;
You need to use LEFT JOIN as you mentioned in Biswabid answer comment I like to show what records is available in table 2 alone
select DISTINCT tb2.*
from table2 tb2
left join table1 tb1 on tb1.id1 = tb2.id1
and tb1.id2 = tb2.id2
WHERE tb1.id1 IS NULL

Joining 2 tables and adding price to give total revenue in MySQL

probably a simple query for someone to answer but I'm new at this and a bit stuck!
Trying to map from one table to another and sum together numbers in a column from Table 1. For example:
Table 1:
Item_ID Price
I0001 3.50
I0002 2.50
Table 2:
Item_ID Date_sold
I0001 10/11/14
I0002 12/11/14
What I want to do is tell MySQL that where 'Date_sold' is 'not null' in Table 2, to identify 'Item_id', match this back to table 1, read the 'Price' column in that row, and then add the results together for total revenue.
Any help appreciated!
I ll try something like that :
SELECT t1.Item_ID, SUM(Price) AS Total
FROM Table1 t1
INNER JOIN Table 2 t2
ON t1.Item_ID = t2.Item_ID
WHERE t2.Sold_date IS NOT NULL
GROUP BY Item_ID;
You will get the grand total by item if you add the group by statement.
If you only want the grand total :
SELECT SUM(Price) AS GrandTotal
FROM Table1 t1
INNER JOIN Table 2 t2
ON t1.Item_ID = t2.Item_ID
WHERE t2.Sold_date IS NOT NULL;
You could join both tales on the item_id, and then group by to sum the price:
SELECT date_sold, SUM(price)
FROM table_2
JOIN table_1 on table_2.item_id = table_1.item_id
WHERE date_sold IS NOT NULL
GROUP BY date_sold
select sum(table1.price) as revenue from table1 join table2 on table1.item_id=table2.item_id where table2.data_sold is not null

How to get value from two table if id is same in sql

I am very new in sql, then i am so confused how to get join or get value from two.
First table:
ID P_ID Name AGE U_ID
1 5 B 8 5w
2 8 D 17 6j
3 7 R 67 0qw
Second Table:
ID P_ID Address Edu
1 6 Bddd +2
2 7 Dssss Bachelor
3 2 rress Phd
Here, i want to get accorading to P_ID, but i have U_ID only.
For this: Let us assume that now I have U_ID=0qw.
How to get value from second table. Address and edu , and Age Thanks in advance.
Join on the column that both tables have in common.
select t1.age, t2.address, t2.edu
from table1 t1
join table2 t2 on t1.p_id = t2.p_id
where t1.u_id = '0qw'
Then use the table names or alias names (like t1 for table1) to pick columns from the tables you join.
I think you are looking forward to this:
SELECT t2.Address, t2.Edu, t1.Age
FROM firstTable t1
JOIN secondTable t2
ON t1.P_ID = t2.P_ID
WHERE t1.U_ID = '0qw'
SELECT table1.AGE
, table2.Address
, table2.Edu
FROM table1
INNER JOIN table2 ON (table1.P_ID = table2.P_ID)
WHERE table1.U_ID = '0qw';
NOTE: SQL query is not case sensitive.