sql optimize a query using the join - sql

I have a table productHistory
productHistory (id_H , id_product , name , tsInsert);
I wanna get from the table productHistory the last product in the giving period (start, end):
tsInsert must be between the start and the end.
I can do like this:
select max(id_H)
from productHistory
where tsInsert>=:start and tsInsert <=:end
group by id_product;
then select all from productHistory where id_H in the previous selection.
This query is very heavy, is there any other solution using the right join for example?

I tried this solution:
SELECT * FROM productHistory x
INNER JOIN
(
SELECT MAX(id_H) as maxId
FROM productHistory
GROUP id_product
) y
ON x.id_H = y.maxId
and x.TSINSERT >=:start and x.TSINSERT <=:end

Related

How to show ONLY the max value of a inner join table column?

I used INNER JOIN on two tables :
Transactions
- transaction_id (PK)
-ticket_id (FK) reference to ticketsforsale
Ticketsforsale :
- ticket_id (PK)
- type
- price
(there are more columns in each table but serve no purpose for this question)
The query i tried is the following :
SELECT ticketsforsale.type , SUM(ticketsforsale.price) AS TotalProfit
FROM ticketsforsale INNER JOIN transactions
ON ticketsforsale.ticket_id = transactions.ticket_id
GROUP BY ticketsforsale.type
The result is :
Sports | 300
Cruise | 600
Theater| 100
I tried using this line in the query
WHERE TotalProfit = SELECT(MAX(TotalProfit)
But I can't figure out the right place for this line.
What i want the query to do is to show only the ROW containing the max value of "TotalProfit" . I am just missing the right MAX function usage on this query , thanks !
Use ORDER BY and a limit the result set to one row:
SELECT tfs.type , SUM(tfs.price) AS TotalProfit
FROM ticketsforsale tfs INNER JOIN
transactions t
ON tfs.ticket_id = t.ticket_id
GROUP BY tfs.type
ORDER BY TotalProfit DESC
FETCH FIRST 1 ROW ONLY;
Note that I introduced table aliases as well, so the query is easier to write and to read.
Based on this query, you don't seem to need the JOIN:
SELECT tfs.type , SUM(tfs.price) AS TotalProfit
FROM ticketsforsale tfs
GROUP BY tfs.type
ORDER BY TotalProfit DESC
FETCH FIRST 1 ROW ONLY;
You can use CTE and pick only one row based on TotalProfit values.
with cte as (
SELECT ticketsforsale.type , SUM(ticketsforsale.price) AS TotalProfit
FROM ticketsforsale INNER JOIN transactions
ON ticketsforsale.ticket_id = transactions.ticket_id
GROUP BY ticketsforsale.type
)
select *
from cte
order by TotalProfit desc
limit 1
If you want to use max(), you can do something like this:
with cte as (
SELECT ticketsforsale.type , SUM(ticketsforsale.price) AS TotalProfit
FROM ticketsforsale INNER JOIN transactions
ON ticketsforsale.ticket_id = transactions.ticket_id
GROUP BY ticketsforsale.type
)
select *
from cte
where TotalProfit = (select max(TotalProfit) from cte)

Joining complex sql oracle select queries

I have a complex query that selects product id values from history and orders.
SELECT ProductID
FROM History h ( SELECT .....) LATEST
WHERE h.ProductId = LATEST.ProductID
AND ....
AND IsActive = true;
This query is too long, so I could not write all of it. But it returns a table like this:
ProdutID
--------
4654654
9879879
5465465
2132188
7894215
....
I want to join this product id result another table that containts ProductId column.
SELECT * FROM MySecondTable;
ProductID Color
--------- -----
4654654 red
9879879 blue
5465465 orange
How can I join these two query?
CTEs are a really simple way to do such a thing:
with t as (<your query here>)
select t.*, t2.color
from t join
MySecondTable t2
on t.ProductId = t2.ProductId;
You could also just add the join to the from clause of the original query.
you could use the firts as inner joined table
SELECT b.*
FROM MySecondTable b
INNER JOIN (
SELECT ProductID
FROM History h ( SELECT .....) LATEST
WHERE h.ProductId = LATEST.ProductID
AND ....
AND IsActive = true;
) t on t.ProductID = b.ProductID

SQL Server values from Detail table

I have 2 tables ItemMaster and ItemDetail, I am creating a report to display columns from both tables.
I want to display First 3 columns from "ItemMaster" table and then Max(FinishDate) and Max(Amount) from "ItemDetail" table.
I tried to generate results as below written query but not working.
Please help
Thanks
SELECT IM.ItemCode,
IM.Customer,
IM.FinYear,
DET.FinishDate,
DET.Amount
FROM ItemMaster AS IM
INNER JOIN ( SELECT MAX(FinishDate) AS FinishDate, MAX(Amount) AS Amount
FROM ItemDetail ID
WHERE IM.ItemCode = ID.ItemCode) AS DET
ON IM.ItemCode = DET.ItemCode
You need to modify the query of the derived table a little bit so as to include a GROUP BY clause:
SELECT IM.ItemCode,
IM.Customer,
IM.FinYear,
DET.FinishDate,
DET.Amount
FROM ItemMaster AS IM
INNER JOIN ( SELECT ID.ItemCode,
MAX(FinishDate) AS FinishDate, MAX(Amount) AS Amount
FROM ItemDetail ID
GROUP BY ID.ItemCode) AS DET
ON IM.ItemCode = DET.ItemCode
Now you can do a proper JOIN on the ItemCode field.
Try this:
SELECT IM.ItemCode ,
IM.Customer ,
IM.FinYear ,
DET.FinishDate ,
DET.Amount
FROM ItemMaster AS IM
CROSS APPLY ( SELECT MAX(FinishDate) AS FinishDate ,
MAX(Amount) AS Amount
FROM ItemDetail ID
WHERE ID.ItemCode = IM.ItemCode
) AS DET
There is no sub-select needed, imho. Just join both tables and aggregate as you would do on a single table:
select im.ItemCode, im.Customer, im.FinYear,
MAX(id.FinishDate), MAX(id.Amount)
from ItemMaster im
join ItemDetail id
on im.ItemCode = id.ItemCode
group by im.ItemCode, im.Customer, im.FinYear

How to group my table for latest date and ID?

I have a table like this:
I need group this table latest date for every ID.
I mean, I want to get last row every ID. Here is my query:
SELECT DISTINCT ch.Date,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, [Date] from tblCommonHistory ) ch
ON ch.TableIDentity = rk.ID order by ID
How can I do what I want?
EDIT: This query worked for me:
SELECT DISTINCT ch.dt,ID FROM dbo.tblrisk AS rk
inner join (Select TableIdentity, max([Date]) as dt from tblCommonHistory group by TableIdentity) ch ON ch.TableIDentity = rk.ID order by ID
Just use aggregation:
select TableIdentity, max([date])
from tblCommonHistory
group by TableIdentity;
Your question only mentions one table. Your query has two; I don't understand the discrepancy.
It's strange that you have duplicated TableIdentity in tblCommonHistory, but otherwise you should not be getting multiple dates for the same ID from your query.
And also, the only reason to join the 2 tables seems to be that you need to skip those ID that are not present in the tblrisk (is it what you need to do?)
In that case, I'd suggest
SELECT max(ch.Date) AS [Date],ID FROM dbo.tblrisk AS rk
inner join tblCommonHistory AS ch ON ch.TableIDentity = rk.ID
group by ID order by ID

Pivot table in SQL Server results in error

Currently I'm trying to learn on pivot table, here is my table diagram.
I want to generate data row in branch name and column with month with sum total in sales.
SELECT *
FROM
(SELECT
BRANCH.NAME, SALES.TOTAL, TIME.MONTH
FROM
SALES
INNER JOIN
BRANCH ON SALES.BRANCH_ID = BRANCH.BRANCH_ID
INNER JOIN
TIME ON SALES.TIME_ID = TIME.TIME_ID
) AS TABLE1
PIVOT (
SUM(SALES.TOTAL) FOR TIME.MONTH IN ([APR],[MAY],[JUN])
) PIVOTTABLE
it shows an error:
The column prefix 'SALES' does not match with a table name or alias name used in the query.
Is it my table structure got problem or just my query are wrong?
Remove Sales and Time prefix or use TABLE1 instead:
PIVOT (
SUM(TOTAL) FOR MONTH IN ([APR],[MAY],[JUN])
) PIVOTTABLE
Try this:
SELECT * FROM
(
SELECT BRANCH.NAME,SALES.TOTAL,TIME.MONTH
FROM SALES
INNER JOIN BRANCH
ON SALES.BRANCH_ID=BRANCH.BRANCH_ID
INNER JOIN TIME
ON SALES.TIME_ID=TIME.TIME_ID
)AS TABLE1
PIVOT (
SUM(TABLE1.TOTAL) FOR TABLE1.MONTH IN ([APR],[MAY],[JUN])
) PIVOTTABLE