SQL Server values from Detail table - sql

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

Related

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

Joining two tables on SQL Server

I have two SQL Server tables: ORDR (orders) and RDR1 (order's items). I'm trying to create a report which shows:
DocEntry, CardName, DocDueDate: info about the order
pTot: total amount of items in the order
ItemCode: item's code (any of them, only one is needed)
Dscription: item's name
My last attempt was:
SELECT
dbo.ORDR.DocEntry, dbo.ORDR.CardName, dbo.ORDR.DocDueDate,
SUM(dbo.RDR1.Quantity) AS pTot,
dbo.RDR1.ItemCode,
dbo.RDR1.Dscription
FROM
dbo.ORDR
INNER JOIN
dbo.RDR1 ON dbo.ORDR.DocEntry = dbo.RDR1.DocEntry
GROUP BY
dbo.ORDR.DocEntry, dbo.ORDR.CardName, dbo.ORDR.DocDueDate,
dbo.RDR1.ItemCode, dbo.RDR1.Dscription
Items' code/name in one order are very similar so I need only the first RDR1's record associated to that order
I have 2 problems:
I'm getting one row for each RDR1 record
pTot is not summing the amount of items
Can you show me how to join these tables properly?
You could use ROW_NUMBER to get the first RDR1 item for each ORDR and SUM OVER to get the total amount of items.
SELECT
o.DocEntry,
o.CardName,
o.DocDueDate,
r.pTot,
r.ItemCode,
r.Dscription
FROM dbo.ORDR o
INNER JOIN (
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY DocEntry ORDER BY ItemCode),
pTot = SUM(Quantity) OVER(PARTITION BY DocEntry)
FROM dbo.RDR1
) r
ON r.DocEntry = o.DocEntry
WHERE r.rn = 1
Additionally, you might want to use meaningful table aliases to improve readability.
Here is my proposed solution.
SELECT
[rowno] = ROW_NUMBER() OVER(PARTITION BY DocEntry ORDER BY ItemCode),
O.DocEntry,
O.CardName,
O.DocDueDate,
SUM(Quantity) AS pTot,
O.ItemCode,
O.Dscription
INTO #TEMP_ORDER
FROM dbo.ORDR O
INNER JOIN dbo.RDR1 R
ON O.DocEntry = dbo.RDR1.DocEntry
GROUP BY O.DocEntry, O.CardName, O.DocDueDate, R.ItemCode, R.Dscription
SELECT
DocEntry,
CardName,
DocDueDate,
pTot,
ItemCode,
Dscription
FROM #TEMP_ORDER
WHERE roWno = 1
DROP TABLE #TEMP_ORDER

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

Get SUMs for dimension record from several fact tables

I have to 2 queries below which calculate to correct value:
Select Finances.CustomerID,
sum(Finances.Total)Total
from Finances
group by Finances.CustomerID
order by Finances.CustomerID
Select Invoices.CustomerID,
sum(Invoices.InvoiceValue)InvoiceValue
from Invoices
group by Invoices.CustomerID
order by Invoices.CustomerID
within the Finances table a customer can owe money from multiple orders, so for this example lets say the customer has to pay £100+ £400 + £500, which totals to £1000.
the customer then receives the 1st invoice for £100, and pays this..
so the 2nd query would now display £100.... from these 2 values I then want to calculate a 3rd column which deducts the £100 away from the £1000 equalling £900 (the amount left to pay)
the is my table structure:
there are a lot more tables associated however this is where I am the data from with the select statements :)
how would i write the sql statement to do this all together or is it not possible? ideally i would like the to be used within a INSERT -> SELECT -> WHERE NOT EXISTS Statement or alternatively populated in a view. thanks for the help
SAMPLE DATA:
CREATE VIEW CustomerFinances AS
;WITH FinancesCTE AS
(
Select Finances.CustomerID,
sum(Finances.Total)Total
from Finances
group by Finances.CustomerID
),InvoicesCTE AS
(
Select Invoices.CustomerID,
sum(Invoices.InvoiceValue)InvoiceValue
from Invoices
group by Invoices.CustomerID
)
SELECT C.*,
F.Total AS FinanceTotal,
I.InvoiceValue
FROM Customers C
LEFT JOIN FinancesCTE F
ON C.CustomerID = F.CustomerID
LEFT JOIN InvoicesCTE I
ON C.CustomerID = I.CustomerID
GO
Try this,
CREATE VIEW CustomerFinanceDetails AS
(
select c.*,isnull(FinanceTotal,0) as FinanceTotal,isnull(InvoiceTotal,0) as InvoiceTotal
from
(select * from Customers) c
left outer join
(select CustomerID,isnull(SUM(Total),0) as FinanceTotal from Finances group by CustomerID) f on c.CustumerID=f.CustomerID
left outer join
(select CustomerID,isnull(SUM(InvoiceValue),0) as InvoiceTotal from Invoices group by CustomerID) i on c.CustumerID= i.CustomerID
)

sql optimize a query using the join

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