Mysql LEFT JOIN with most recent record? - mysql

I have this query:
SELECT A.ISIN, A.CUSIP, A.Currency, A.StatedFinalMaturityDate,
A.FirstPayDate, A.PaymentDelay, A.trancheName, A.DealTicker,
B.TrancheCoupon, B.OneMonthCoupon, B.SettleDate, B.Factor,
B.paymentDate
from table1 A
left JOIN table2 B on (A.DealTicker = B.DealTicker AND A.trancheName=B.trancheName)
where A.ISIN IN ('XS2004372095','XS1679333432','XS0333340361',
'XS0333337813','XS0333324241','XS0333323862',
'XS0333323516','XS0333323193','XS0333316908',
'XS0333313988','USWFMW0N9Z05','USWFHZ5XIY05',
'USWFHVA6TK04','USWFHTXSQJ03');
Here table1 have one record correspond to each ISIN but the table2 can have multiple rows.
table2 has settleDate column which show latest row. So I want to select only latest row from table2 only. Since table2 need two JOINING column I m little confused here.
PS: I cannot use mysql 8 features like row_number() as mysql server version is 5.7. And my table contains more than 150millions records. I tried a approaches but didn't work because of huge data.

You are using a very old MySQL version, so you cannot use windows functions but must access the same table twice. You can use NOT EXISTS or MAX to get the last rows. Here is an example with MAX:
SELECT
a.isin, a.cusip, a.currency, a.statedfinalmaturitydate, a.firstpaydate,
a.paymentdelay, a.tranchename, a.dealticker, b.tranchecoupon,
b.onemonthcoupon, b.settledate, b.factor, b.paymentdate
FROM table1 a
LEFT JOIN
(
SELECT *
FROM table2
WHERE (dealticker, tranchename, settledate) IN
(
SELECT dealticker, tranchename, max(settledate)
FROM table2
GROUP BY dealticker, tranchename
)
) b ON b.dealticker = a.dealticker AND b.tranchename = a.tranchename
where a.isin IN ('XS2004372095','XS1679333432','XS0333340361','XS0333337813',
'XS0333324241','XS0333323862','XS0333323516','XS0333323193',
'XS0333316908','XS0333313988','USWFMW0N9Z05','USWFHZ5XIY05',
'USWFHVA6TK04','USWFHTXSQJ03');

You can use window functions:
SELECT A.ISIN, A.CUSIP, A.Currency, A.StatedFinalMaturityDate, A.FirstPayDate, A.PaymentDelay, A.trancheName, A.DealTicker,
B.TrancheCoupon, B.OneMonthCoupon, B.SettleDate, B.Factor, B.paymentDate
FROM table1 A LEFT JOIN
(SELECT b.*,
ROW_NUMBER() OVER (PARTITION BY DealTicker, trancheName ORDER BY settleDate DESC) as seqnum
FROM table2 B
) B
ON A.DealTicker = B.DealTicker AND
A.trancheName = B.trancheName AND
B.seqnum = 1
WHERE A.ISIN IN ('XS2004372095','XS1679333432','XS0333340361','XS0333337813','XS0333324241','XS0333323862','XS0333323516','XS0333323193','XS0333316908','XS0333313988','USWFMW0N9Z05','USWFHZ5XIY05','USWFHVA6TK04','USWFHTXSQJ03');
In older versions of MySQL, you can use:
SELECT A.ISIN, A.CUSIP, A.Currency, A.StatedFinalMaturityDate, A.FirstPayDate, A.PaymentDelay, A.trancheName, A.DealTicker,
B.TrancheCoupon, B.OneMonthCoupon, B.SettleDate, B.Factor, B.paymentDate
FROM table1 A LEFT JOIN
table2 B
ON A.DealTicker = B.DealTicker AND
A.trancheName = B.trancheName AND
B.settleDate = (SELECT MAX(b2.settleDate)
FROM table2 b2
WHERE b2.DealTicker = B.DealTicker AND
b2.trancheName = B.trancheName
)
WHERE A.ISIN IN ('XS2004372095','XS1679333432','XS0333340361','XS0333337813','XS0333324241','XS0333323862','XS0333323516','XS0333323193','XS0333316908','XS0333313988','USWFMW0N9Z05','USWFHZ5XIY05','USWFHVA6TK04','USWFHTXSQJ03');

Related

Cross apply in MY SQL

Am trying to convert this Sql server script to mysql.
SELECT A.*
FROM TableA A
CROSS APPLY
(
SELECT TOP 1 UID
FROM TableB
WHERE BetID = A.BetID
AND BETCODE = A.BETCODE
ORDER BY CASE WHEN InfoCode > '' THEN 0 ELSE 1 END,UID
)Z
WHERE Z.UID = A.UID
Can please advise as how, I know I can change CROSS JOIN and Limit 1 but still it fails
in you can't use TOP but use limit so you could try and in MySql the scope for subquery table is differente respect to SQL_SERVER so you must buil the join inside the subquery
SELECT A.*
FROM TableA A
CROSS JOIN
( SELECT UID
FROM TableB
INNER JOIN TABLEA A ON BetID = A.BetID
AND BETCODE = A.BETCODE
ORDER BY CASE WHEN InfoCode > '' THEN 0 ELSE 1 END,UID
LIMIT 1
) Z
WHERE Z.UID = A.UID
or a cross join with a single result could be also translate as an inner join
SELECT A.*
FROM TableA A
INNER JOIN
( SELECT UID
FROM TableB
INNER JOIN TABLEA A ON BetID = A.BetID
AND BETCODE = A.BETCODE
ORDER BY CASE WHEN InfoCode > '' THEN 0 ELSE 1 END,UID
LIMIT 1
) Z ON Z.UID = A.UID

Use where clause in temporary table

I am trying to use where clause in temporary table. Actually i used it but results aren't true. trying to find products between 2 dates but when i use where clause it gets no data.
CREATE TABLE #TEMPCOZGU
(
ROW INT,
TEZGAH VARCHAR(50),
COZGU VARCHAR(50),
PERSONEL VARCHAR(50),
DATE DATETIME,
FIRE INT,
FIRE_METRE NUMERIC(25,6)
)
INSERT INTO #TEMPCOZGU
select row_number() over(order by TEZGAH) AS ROW, TEZGAH, COZGU, PERSONEL, TARIH, FIRE, FIRE_METRE
from cozgu_fırelerı
where tezgah = 'M01' and cozgu = 'SAĞ ALT BAĞLANTI'
SELECT T1.TEZGAH, T1.COZGU, T1.PERSONEL,T1.FIRE, T1.FIRE_METRE, t1.DATE, T2.DATE AS PREVIOUSDATE, ISNULL(DATEDIFF(DAY, T2.DATE, T1.DATE), 0) AS GUNFARKI , SUM(MKARE) AS TOPLAMMKARE
FROM #TEMPCOZGU as t1
left outer join #TEMPCOZGU as t2 on t1.row-1 = t2.row
left outer join HALI_TEZGAH AS TE ON T1.TEZGAH = TE.TEZGAH_NO
LEFT OUTER JOIN HALI_GUNLUK_URETIM AS U ON U.TEZGAH = TE.ID
--WHERE U.TARIH BETWEEN T1.TARIH AND T2.TARIH
GROUP BY T1.TEZGAH, T1.COZGU, T1.PERSONEL, T1.DATE,T1.FIRE, T1.FIRE_METRE, T2.DATE
drop table #TEMPCOZGU`
If the datetime values always have the time set to "00:00:00", try
SELECT T1.TEZGAH, T1.COZGU, T1.PERSONEL,T1.FIRE, T1.FIRE_METRE, t1.DATE, T2.DATE AS PREVIOUSDATE, ISNULL(DATEDIFF(DAY, T2.DATE, T1.DATE), 0) AS GUNFARKI , SUM(MKARE) AS TOPLAMMKARE
FROM #TEMPCOZGU as t1
left outer join #TEMPCOZGU as t2 on t1.row-1 = t2.row
left outer join HALI_TEZGAH AS TE ON T1.TEZGAH = TE.TEZGAH_NO
LEFT OUTER JOIN HALI_GUNLUK_URETIM AS U ON U.TEZGAH = TE.ID
WHERE U.TARIH >= T1.TARIH AND U.TARIH < DateADD (T2.TARIH, INTERVAL 1 DAY)
GROUP BY T1.TEZGAH, T1.COZGU, T1.PERSONEL, T1.DATE,T1.FIRE, T1.FIRE_METRE, T2.DATE
If that's not the case, then your between should have worked in the first place.

MySQL - is a sub query what's needed here?

I currently have such a query:
SELECT
sec_to_time(avg(t1.sessiontime)) as aloc,
count(*) as calls
FROM
table1 AS t1
inner join
table2 as t2 ON t1.destination = t2.prefix
WHERE
t1.card_id = '101'
AND
t1.terminatecauseid = 1
group by t1.destination
Example result:
The 'calls' data is bound to 't1.terminatecauseid = 1' (meaning only answered calls)
I'd like to have a percentage of answered calles from the total calls made.
the same query without the condition (t1.terminatecauseid = 1) will give me the total calls made.
I'd like to know what is the best way to add another column called 'Average Success Rate' that will do:
total-calls*successful-calls/100
Is a subquery what's needed here? or a brand new and different query?
SELECT
sec_to_time(avg(t1.sessiontime)) as aloc,
sum(t1.terminatecauseid = 1) * 100 / count(*) as Average_Success_Rate,
sum(t1.terminatecauseid = 1) as calls
FROM
table1 AS t1
inner join
table2 as t2 ON t1.destination = t2.prefix
WHERE
t1.card_id = '101'
group by t1.destination

Update mysql rows with value extracted from counting another table

I have the following query:
SELECT int_intrebari.id, COUNT( id_raspuns ) AS nr_raspunsuri
FROM int_intrebari, int_raspunsuri
WHERE int_intrebari.id = int_raspunsuri.id
GROUP BY id
Is it possible to update first table with nr_raspunsuri from the query, without writing a foreach statement?
You can UPDATE with JOIN like so:
UPDATE int_intrebari i1
INNER JOIN
(
SELECT id, COUNT( id_raspuns ) AS nr_raspunsuri
FROM int_intrebari
GROUP BY id
) i2 ON i1.id = i2.id
SET i1.nr_raspunsuri = i2.nr_raspunsuri
You can do it like -
update int_intrebari left join int_raspunsuri on int_intrebari.id =int_raspunsuri.id
set int_intrebari.column_to_update = int_raspunsuri.column_from_update_second_table
UPDATE
(SELECT int_intrebari.id, COUNT( id_raspuns) AS nr_raspunsuri
FROM int_intrebari, int_raspunsuri
WHERE int_intrebari.id = int_raspunsuri.id
GROUP BY id) t1,
int_raspunsuri t2
SET
t2.nr_raspunsuri=t1.nr_raspunsuri
WHERE
t1.id=t2.id

MYSQL UNION and ORDER BY not working

I have a mysql query which is as follows
(SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable.osa_id,
order_stockavailable.of_id,
order_stockavailable.osa_stocka,
order_category.ocat_name
FROM
order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id)
UNION
(SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable_attributes.id,
order_stockavailable_attributes.of_id,
order_stockavailable_attributes.opap_stock,
order_category.ocat_name
FROM order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id
LEFT JOIN order_stockavailable_attributes
ON order_product.op_id = order_stockavailable_attributes.op_id)
ORDER BY order_product.op_name
The query is givng error, T
Table 'order_product' from one of the SELECTs cannot be used in global ORDER clause
I checked the MYSQL manual, but am not getting any clue, any help would be really great.
SELECT *
FROM (
SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable.osa_id,
order_stockavailable.of_id,
order_stockavailable.osa_stocka,
order_category.ocat_name
FROM
order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id
UNION
SELECT order_product.op_id,
order_product.ocat_id,
order_product.op_partnunber,
order_product.op_name,
order_product.op_upc,
order_product.op_desc,
order_stockavailable_attributes.id,
order_stockavailable_attributes.of_id,
order_stockavailable_attributes.opap_stock,
order_category.ocat_name
FROM order_product
LEFT JOIN order_category
ON order_product.ocat_id = order_category.ocat_id
LEFT JOIN order_stockavailable
ON order_product.op_id = order_stockavailable.op_id
LEFT JOIN order_stockavailable_attributes
ON order_product.op_id = order_stockavailable_attributes.op_id
) t
ORDER BY op_name
Btw: there is no need to put the individual SELECTs of a UNION into brackets.
Try the following syntax?
SELECT
x, y
FROM
(
SELECT x, y FROM z
UNION
SELECT a, b FROM c
)
ORDER BY
x, y
Try
order by op_name
instead of
ORDER BY order_product.op_name
SELECT *
FROM (SELECT order_product.op_id,
...
FROM
... )
UNION
(SELECT order_product.op_id,
...
FROM order_product
... ) U
ORDER BY op_name;