SQL select query with two tables - sql

I'm struggling with a task. I need to create a select query which:
For each specific listed date shows date and revenue where revenue is number of sold units multiplied with unit price (but ONLY if revenue is greater than or equal to 10 000).
There are two tables: product & order.
Product contains columns: unittype, price. And order contains columns: unittype, date, number (number of units sold)
This is my try on the select query:
SELECT
order.date,
product.price*order.number AS revenue
FROM product
INNER JOIN
order
ON product.unittype = order.unittype
WHERE product.price*order.number >= 10000;
None of my results are even close to 10k (between 39 and 1.3k) so I'm wondering if I've typed it wrong or if there are any more efficient ways to type it?

If this is meant to be for the total for the day (and not the individual line), you need an aggregate and a having clause:
SELECT
order.date,
SUM(product.price*order.number) AS revenue
FROM product
INNER JOIN
order
ON product.unittype = order.unittype
GROUP BY order.date
HAVING SUM(product.price*order.number) >= 10000

Related

Multiple sum subqueries for percentage

I need help with the following problem: I want to make a query that contains multiples sums and then takes those sums and uses them to get a percentage: percentage= s1/s1+s2.
I have as input the following data:
Orders shipping date, Nb of orders that have arrived late, Nb of orders that have arrived on time
What I want as output: The percentage of orders that have arrived late and orders that have arrived on time.
I want another column in the table that will have the percentage using SQL.
Concrete example:
*On 2022/01/04 **10:00 AM** I have 3 orders late and 4 order on time=> 7 orders in total. Percentage=3/7 (late), (4/7) on time
*At 2022/01/04 **11:00 AM** I have 5 orders late and 6 orders on time=>11 orders in total (but all this entry is summed with the previous entry so:) <=> 5+3 orders late, 4+6 orders on time, 18 orders in total => percentage= 8/18 late, 10 on time.
In order to sum previous entries order numbers with status "LATE" to current on time order number I wrote the following sql:
(sum1=s1)
SELECT s1.EventDate, (
SELECT SUM(s2.NbOfOrders)
FROM OrderShipmentStats s2
WHERE s2.EventDate <= s1.EventDate AND s2.Status='LATE'
) AS cnt
FROM OrderShipmentStats s1
GROUP BY s1.EventDate, s1.Status
The same kind of sql was written for "On Time" and it works. But what I need to do now is get the values and add them together of the two sql queries and based on the status which is late or on time do s1/s1+s2 or s2/s2+s1.
My problem is that I do not know how to do this formula in a single query using those 2 subqueries, any help would be great.
Picture with Table
Above there is the link with the picture containing how the table looks(I am new so I am not allowed to embed a photo).
The percentage column is the one I will add and there are lines pointing towards how that is calculated.
I created the table based on your image and added a few rows to it.
In the query you could see total orders count per hour, per status and the grand total as you mentioned in the image.
The query looks like:
create table OrderShipmentsStats
(
EventDate datetime not null,
Status varchar(10) not null,
OrdersCount int not null
)
insert into OrderShipmentsStats
values
('2022-01-04T10:00:00','Late',3),
('2022-01-04T10:00:00','On Time',4),
('2022-01-04T11:00:00','Late',5),
('2022-01-04T11:00:00','On Time',6),
('2022-01-04T12:00:00','Late',1),
('2022-01-04T12:00:00','On Time',2)
SELECT
EventDate,
Status,
OrdersCount,
TotalPerHour,
StatusTotal,
GrandStatusTotal,
-- at the line below, multiplying by 1.0 will convert the result and we would receive smth like 0.45, 0.123, some percentage
-- but we want the actual percent like 15%, or 50%. to obtain it, just multiply by 100
cast(1.0 * o.StatusTotal / o.GrandStatusTotal as decimal(5,3)) * 100 as Percentage
from
(
select
EventDate,
Status,
OrdersCount,
TotalPerHour,
StatusTotal,
SUM(TotalPerHour) over (partition by Status order by EventDate asc) as GrandStatusTotal
from
(
select
EventDate,
Status,
OrdersCount,
Sum(OrdersCount) over (partition by EventDate order by EventDate asc) as TotalPerHour,
SUM(OrdersCount) over (partition by Status order by EventDate asc) as StatusTotal
from OrderShipmentsStats
) as t
) as o
order by EventDate, Status

Find the price of an item in an order. The price of the item is the price negotiated for the order’s contract (5/day)

I have an SQL project and that's one of the questions.
I have:
SELECT * FROM ToSupply
ORDER By ContractPrice;
This is my first SQL project, and 5/day means it should happen 5 times a day, how do I do that? Is there a method to repeat something after a set amount of time?
In order to find the price of an item in an order for a particular day, you would need a column that expresses a DateTime value; let's call that 'OrderDay'.
If the price of the item is the price negotiated for the order’s contract, and only five orders are supplied per day, then this query is closer to what you desire:
SELECT AVG(ts.ContractPrice)/5
FROM ToSupply ts
JOIN
(
SELECT OrderyDay, count(*)
FROM ToSupply
GROUP BY OrderDay
HAVING count(*) = 5
) o5
ON ts.OrderDay = o5.OrderDay
GROUP BY ts.OrderDay
ORDER By AVG(ts.ContractPrice)/5;

How to get the sum of transaction amount happened in one date?

I am trying to write a query that will give me transaction amount sum happened in one date. The problem is , when I added column date in my query, I get individual values not their sum. The requirement for this query is to have one entry for each merchant but i am getting multiple rows for one merchant.
SELECT SUBSTR(m.MERCHANTLASTNAME, 1, 36) Name1,
m.MERCHANTBANKBSB MerchantAccbsb,
m.MERCHANTBANKACCNR Merchant_act,
m.MERCHANTID merchantid,
t.transactiondate date1,
sum(t.TRANSACTIONAMOUNT) as total
FROM fss_merchant m
JOIN fss_terminal term
ON m.MERCHANTID = term.MERCHANTID
JOIN FSS_DAILY_TRANSACTION t
ON term.TERMINALID = t.TERMINALID
group by t.transactiondate, SUBSTR(m.MERCHANTLASTNAME, 1, 36), m.MERCHANTID, m.MERCHANTBANKBSB, m.MERCHANTBANKACCNR,
m.MERCHANTLASTNAME
Output of my query:
I want to get one entry per each merchant with the sum of transaction amount in one day, not multiple rows of transaction in that day.
You can calculate the total amount in different inner query with the truncated date and join it with FSS_MERCHANT table so that issues described by #SatishSK and #mangusta is taken care.
You can use the following query:
SELECT
SUBSTR(M.MERCHANTLASTNAME, 1, 36) NAME1,
M.MERCHANTBANKBSB MERCHANTACCBSB,
M.MERCHANTBANKACCNR MERCHANT_ACT,
M.MERCHANTID MERCHANTID,
M_DATA.TRANSACTIONDATE DATE1,
M_DATA.TOTAL AS TOTAL
FROM
FSS_MERCHANT M
INNER JOIN (
SELECT
TERM.MERCHANTID MERCHANTID,
TRUNC(T.TRANSACTIONDATE) TRANSACTIONDATE,
SUM(T.TRANSACTIONAMOUNT) AS TOTAL
FROM
FSS_TERMINAL TERM
JOIN FSS_DAILY_TRANSACTION T ON TERM.TERMINALID = T.TERMINALID
GROUP BY
TERM.MERCHANTID,
TRUNC(T.TRANSACTIONDATE)
) M_DATA ON ( M.MERCHANTID = M_DATA.MERCHANTID );
Good luck!!
t.transactiondate column might contain date+time values. Use TRUNC(t.transactiondate) where you are using just t.transactiondate. You will get sum(transaction amount) "Date-wise" for each merchant.
OR
Filter out rows based on "Date" value in WHERE clause to retrieve data pertaining to a specific date.
Probably the reason is that you have included both m.MERCHANTLASTNAME and SUBSTR(m.MERCHANTLASTNAME,1,36) into the group by clause.
In case if there are entries with same SUBSTR(m.MERCHANTLASTNAME,1,36) but different m.MERCHANTLASTNAME, this is going to yield duplicates. You need to remove m.MERCHANTLASTNAME from group by clause

Use query result

I´m having issues with the following query. I have two tables; Table Orderheader and table Bought. The first query I execute gives me, for example, two dates. Based on these two dates, I need to find Production data AND, based on the production data, I need to find the Bought data, and combine those data together. Lets say I do the following:
Select Lotdate From Orderheader where orhsysid = 1
This results in two rows: '2019-02-05' and '2019-02-04'. Now I need to do two things: I need two run two queries using this result set. The first one is easy; use the dates returned and get a sum of column A like this:
Select date, SUM(Amount) from Orderheader where date = Sales.date() [use the two dates here]
The second one is slighty more complicated, I need to find the last day where something has been bought based on the two dates. Production is everyday so Productiondate=Sales.date()-1. But Bought is derived from Productionday and is not everyday so for every Productionday it needs to find the last Boughtday. So I can't say where date = Orderheader.date. I need to do something like:
Select date, SUM(Amount)
FROM Bought
WHERE date = (
SELECT top 1 date
FROM Bought
WHERE date < Orderheader.date)
But twice, for both the dates I got.
This needs to result in 1 table giving me:
Bought.date, Bought.SUM(AMOUNT), Orderheader.date, Orderheader.SUM(AMOUNT)
All based on the, possible multiple, Lotdate(s) I got from the first query from Sales table.
I've been struggling with this for a moment now, using joins and nested queries but I can't seem to figure it out!
Example sample:
SELECT CONVERT(date,ORF.orfDate) as Productiedatum, SUM(orlQuantityRegistered) as 'Aantal'
FROM OrderHeader ORH
LEFT JOIN OrderFrame ORF ON ORH.orhFrameSysID = ORF.orfSysID
LEFT JOIN OrderLine ORL ON ORL.orhSysID = ORH.orhSysID
LEFT JOIN Item ON Item.itmSysID = ORL.orlitmSysID
where CONVERT(date,ORF.orfDate) IN
(
SELECT DISTINCT(CONVERT(date, Lot.lotproductiondate)) as Productiedatum
FROM OrderHeader ORH
LEFT JOIN Registration reg ON reg.regorhSysID = ORH.orhSysID
LEFT JOIN StockRegistration stcreg ON stcreg.stcregRegistrationSysID = reg.regSysID
LEFT JOIN Lot ON Lot.lotSysID = stcregSrclotSysID
WHERE ORH.orhSysID = 514955
AND regRevokeRegSysID IS NULL
AND stcregSrcitmSysID = 5103
)
AND ORL.orlitmSysID = 5103
AND orldirSysID = 2
AND NOT orlQuantityRegistered IS NULL
GROUP BY Orf.orfDate
Sample output:
Productiedatum Aantal
2019-02-05 20
2019-02-06 20
Here I used a nested subquery to get the results from 'Production' (orderheader) because I just can use date = date. I'm struggling with the Sales part where I need to find the last date(s) and use those dates in the Sales table to get the sum of that date.
Expected output:
Productiedatum Aantal Boughtdate Aantal
2019-02-04 20 2019-02-01 55
2019-02-05 20 2019-02-04 60
Try this.
IF OBJECT_ID('tempdb..#Production') IS NOT NULL DROP TABLE #Production
IF OBJECT_ID('tempdb..#Bought') IS NOT NULL DROP TABLE #Bought
CREATE table #Production(R_NO int,ProductionDate datetime,ProductionAmount float)
CREATE table #Bought(R_NO int,Boughtdate datetime,Boughtamount float)
insert into #Production(ProductionDate,ProductionAmount,R_NO)
select p.date ProductionDate,sum(Amount) ProductionAmount,row_number()over (order by p.date) R_NO
from Production P
join Sales s on p.date=S.date-1
where orhsysid=1
group by p.date
declare #loop int,#ProdDate datetime
select #loop =max(R_NO) from #Production
while (1<=#loop)
begin
select #ProdDate=ProductionDate from #Production where r_no=#loop
insert into #Bought(Boughtdate,Boughtamount,R_NO)
select Date,Sum(Amount),#loop R_NO from Bought where date=(
select max(date) from bought B
where B.Date<#ProdDate)
group by Date
set #loop=#loop-1
end
select ProductionDate,ProductionAmount,Boughtdate,Boughtamount from #Bought B
join #Production p on B.R_NO=P.R_NO

getting avg of column based on the result set

I have a select statement that divides the count of sales by country, priceBanding (see example below)
The select statement looks like follows:
SELECT p.[Price Band]
,t.[Country]
,o.COUNT([Order]) as [Order Count]
FROM #price p (temp table)
INNER JOIN country t ON p.CountryCode = t.countryCode
INNER JOIN sales o ON o.salesValue >= p.startPrice and s.salesValue < p.endPrice
What i want to be able to do is based on this result i want to get an avg of the unit count i.e. For all orders that are under 20 what is the avg unit counts and the same for all others. How can i do this?
Its most likely simple but I cant think through it.
What I am after:
So as you can see, in the price band <20 in UK the order count is 50, and the avg Units of that is 2. As i mentioned earlier, I want the Avg Units of all orders that are under 20 (which is 50 in the picture).
Is that clearer?
Thanks in advance.
EDIT:
The first table: assume it to be the source
And the second table gets the avg, that's what I am after.
Wouldn't you just use avg()?
SELECT p.[Price Band], t.[Country],
o.COUNT(*) as [Order Count],
AVG(Items)
FROM #price p INNER JOIN
country t
ON p.CountryCode = t.countryCode INNER JOIN
sales o
ON o.salesValue >= p.startPrice and s.salesValue < p.endPrice
GROUP BY p.[Price Band], t.[Country]
ORDER BY t.[Country], p.[Price Band]
Note: SQL Server does integer division of integers (so 3/2 = 1 not 1.5) and similarly for AVG(). It is more accurate to use a decimal point number. An easy way is to use AVG(items * 1.0).