How to optimize multiple sub-queries from multiple tables? - mysql

I have two Table such as tnx_lc_invoice and tnx_lc_payment. I want to generate report from this two tables.
Table schema like below images
tnx_lc_payment
tnx_lc_invoice
I want to generate output like below images
output
I am trying below query and its generate similar output. but i want to optimize this query or any alternative solution for faster result.
SELECT
a.lc_no,
a.invoiceValue,
b.paymentValue,
(
a.invoiceValue - b.paymentValue
) AS shortPaymentValue
FROM
(
SELECT
lc_no,
sum(invoice_value) AS invoiceValue
FROM
tnx_lc_invoice
GROUP BY
lc_no
) a
INNER JOIN (
SELECT
lc_no,
sum(payment_value) AS paymentValue
FROM
tnx_lc_payment
GROUP BY
lc_no
) b ON a.lc_no = b.lc_no
If any other alternative easy solution please let me know.Thanks in advance.

Instead of using subqueries create an inner direct between them
SELECT
a.lc_no,
sum(a.invoice_value) AS invoiceValue,
sum(b.payment_value) AS payment_value,
(sum(a.invoice_value) - sum(b.paymentValue)) AS shortPaymentValue
FROM tnx_lc_invoice a
INNER JOIN tnx_lc_payment b
ON a.lc_no = b.lc_no
GROUP BY
a.lc_no
The query was not correct because it multiply the rows if both invoice and payments are duplicated on the same lc_no.
So it is necessary to add at least one group by in an inner query.
SELECT
a.lc_no,
sum(a.invoice_value) AS invoiceValue,
sum(b.payment_value) AS payment_value,
sum(a.invoice_value) - sum(b.payment_Value) AS shortPaymentValue
FROM (select lc_no, sum(invoice_value) as invoice_value
from tnx_lc_invoice group by lc_no) a
INNER JOIN tnx_lc_payment b
ON a.lc_no = b.lc_no
GROUP BY
a.lc_no

Related

Mysql - I have 3 unique tables, need a hint on getting the details with the count

I have 3 tables which are interconnected and i want to select columns from two tables and counts from table 3. If anyone is aware on this, any hint would be appreciated.
Below is the sql i tried, but the count is getting repeated
SELECT distinct p.p_id, p.p_f6, p.p_l4,m.m_id, (
SELECT COUNT(*)
FROM ttokens t where t.pdetail_id = p.pdetail_id
) AS token_count
FROM tparking p,ttokens t LEFT join ttokens_md m ON t.trefn_id = m.trefn_id
WHERE t.pdetail_id = p.pdetail_id
You can try to use JOIN with subquery to get your count instead of selcet subquery.
SELECT p.p_id, p.p_f6, p.p_l4,m.m_id,t.cnt
FROM tparking p
JOIN (
SELECT pdetail_id,COUNT(*) cnt
FROM ttokens
GROUP BY pdetail_id
) t ON t.pdetail_id = p.pdetail_id
LEFT join ttokens_md m ON t.trefn_id = m.trefn_id
Note
I would use JOIN instead of , comma with where condition to connect two tables,, is an old style.

Performing queries on based on the output of a subquery

I am trying to perform a query based on the output of a sub-query. I would join the tables and perform one big query but that forces the query to search the entire table of one of the tables. The goal is to have the who (from table1), the what (from table2) and the when (from table3).
Here's what I have,
SELECT
DB1.TB1.`Date`,
DB1.TB1.`Sequence`,
DB1.TB1.`InstanceId`
FROM
(
SELECT
DB1.TB2.`UserName` AS USER,
DB1.TB2.`FirstName`,
DB1.TB2.`LastName`,
DB1.TB3.`ObjectName` AS OBJECT,
DB1.TB3.`ObjectType`
FROM
DB1.TB2
INNER JOIN DB1.TB3 ON DB1.TB2.`UserName` = DB1.TB3.`UserName`
INNER JOIN DB1.TB4 ON DB1.TB3.`ObjectName` = DB1.TB4.`ObjectName`
WHERE
DB1.TB4.`ADD` = 'Y' AND
DB1.TB2.`ADUC` NOT LIKE 'ServiceAccount' AND
DB1.TB3.`ObjectName` NOT IN ('ThisAdmin','ThatAdmin')
) AS MySubQuery
WHERE
DB1.TB1.`UserName` LIKE 'USER' AND
DB1.TB1.`ActionDetail` LIKE '%OBJECT%'
ORDER BY
DB1.TB1.`Date` DESC LIMIT 1

Join another table in this sql query

I'm using this one to get related softwares based on their keywords. Now I want to add one more condition that is in another table called software_status having software_id. I found this query on SO, so I can't understand it and can't edit it further.
SELECT softwares.*, count(DISTINCT similar.kid) as shared_tags
FROM softwares
INNER JOIN ( keywords_softwares AS this_software INNER JOIN keywords_softwares AS similar USING (kid) ) ON similar.sid = softwares.id
WHERE this_software.sid=:id
AND softwares.id != this_software.sid
AND (softwares.subcategory = :subcatid or softwares.category = :catid)
GROUP BY softwares.id
ORDER BY shared_tags DESC LIMIT 10

Need mysql query to pull data from two tables

So after helpful feedback from my original question, I now have this query:
SELECT sessions.id, sessions.title, sessions.abstract, sessions.presenters, sessions.proposal_id, proposals.outcomes, proposals.CategorySelection, proposals.research3, proposals.research4, proposals.research5, proposals.research6, proposals.innovation3, proposals.innovation4, proposals.innovation5,proposals.innovation6, proposals.application3, proposals.application4, proposals.application5, proposals.application6, proposals.integration3, proposals.integration4, proposals.integration5, proposals.integration6, proposals.references, proposals.organization
FROM sessions, proposals
INNER JOIN proposals ON proposals.id = sessions.proposal_id
WHERE sessions.id = '$id
LIMIT 1;)
that is getting me nowhere fast. What am I doing wrong?
Original question:
I need to pull several fields from one table and several more from a second table. The criteria is that a field called proposal_id match the id field of the second table. I am fairly new so this is what I have so far. It is not working, but not sure how to make it work.
(SELECT `title`,`abstract`,`presenters`,`proposal_id` FROM `sessions` WHERE `id`='$id')
UNION
(SELECT `outcomes`,`CategorySelection`,`research3`,`research4`,`research5`,`research6`,`innovation3`,`innovation4`,`innovation5`,
`innovation6`,`application3`,`application4`,`application5`,`application6`,`integration3`,`integration4`,`integration5`,`integration6`,`references`,`organization` FROM `proposals` WHERE `id`= `sessions`.`proposal_id`)
LIMIT 1;
You need to use JOIN not UNION
select
s.*,p.*
from `sessions` s
inner join `proposals` p on p.id = s.proposal_id
where s.id = '$id'
This is how you can join both the tables using the common key between.
You can select the specific fields instead of .* by specifying the column names as
s.col1,s.col2,p.col1,p.col2
etc
Try to use JOINS, where you can match the related fields from both the tables , this is the most convenient way to fetch records from multiple tables
UNION is used when you want to combine two queries
select a.id,b.some_field from table1 as a
INNER JOIN table2 as b ON b.prospal_id = a.id

MySQL MAX(datetime) not working

I am trying to retrieve the max(date_entered) for a group of computer_ids.
The first query won't return accurate results. The second query gives me accurate results but essentially hangs unless I filter by a specific computer_id.
I'd rather use this first query
SELECT *, max(reports.date_entered)
FROM reports, hardware_reports
WHERE reports.report_id=hardware_reports.report_id
GROUP BY computer_id;
than this second query
SELECT *
FROM reports a
JOIN hardware_reports
ON a.report_id=hardware_reports.report_id
AND a.date_entered = (
SELECT MAX(date_entered)
FROM reports AS b
WHERE a.computer_id = b.computer_id)
and computer_id = 1648;
I need to either optimize second or get max to work in first.
You can alternative join it on a subquery that gets the latest record for every computer_ID.
SELECT a.*, c.*
FROM reports a
INNER JOIN
(
SELECT computer_ID, MAX(date_entered) date_entered
FROM reports
GROUP BY computer_ID
) b ON a.computer_ID = b.computer_ID
AND a.date_entered = b.date_entered
INNER JOIN hardware_reports c
ON a.report_id = c.report_id
To make it more efficient, provide an index on columns:
ALTER TABLE reports INDEX idx_report_compDate (computer_ID, date_entered)