SQL Nested Query Calculation - sql

SELECT *,
(select SUM(sl.priceeach*sl.qty) as 'tot'
from salesline sl where sl.soid=so.soid) as 'total',
so.total,
so.discount,
so.tax
from salesorder so
I am trying to figure out this query but I couldn't display the total in another coloumn
to display the tax included and discount minused data
ERROR : #1054 - Unknown column 'so.total' in 'field list'
whats wrong with my query ?

First you do not want to use a correlated subquery for this. In fact, you should alost never use them at all as they process row-by-agonizing-row like a cursor.
A CTE or derived table will do the job.
SELECT a.total,
so.discount,
so.tax
FROM salesorder so
JOIN
(SELECT sl.soid,SUM(sl.priceeach*sl.qty) AS 'total'
FROM salesline sl GROUP BY sl.soid) A
ON A.soid = so.soid
Now total is an available column to use in other calculations in your query such as:
SELECT a.total,
so.discount,
so.tax,
so.tax*a.total as TaxableAmount
FROM salesorder so
JOIN
(SELECT sl.soid,SUM(sl.priceeach*sl.qty) AS 'total'
FROM salesline sl GROUP BY sl.soid) A
ON A.soid = so.soid

Related

Group By and Inner Join Together To Get Unique Values By Maximum Date

I have a table here in which I want to write a SELECT query in SQL Server that allows me to get the following:
For each unique combination of SalesPerson x Country, get only the rows with the latest Upload_DateTime
However, I am trying to do a group-by and inner join, but to no avail. My code is something like this:
SELECT t1.[SalesPerson], t1.[Country], MAX(t1.[Upload_DateTime]) as [Upload_DateTime]
FROM [dbo].[CommentTable] AS t1
GROUP BY t1.[SalesPerson], t1.[Country]
INNER JOIN SELECT * FROM [dbo].[CommentTable] as t2 ON t1.[SalesPerson] = t2.[SalesPerson], t1.[Country] = t2.[Country]
It seems like the GROUP BY needs to be done outside of the INNER JOIN? How does that work? I get an error when I run the query and it seems my SQL is not right.
Basically, this subquery will fetch the person, the country and the latest date:
SELECT
SalesPerson, Country, MAX(uplodaed_datetime)
FROM CommentTable
GROUP BY SalesPerson, Country;
This can be used on a lot of ways (for example with JOIN or with an IN clause).
The main query will add the remaing columns to the result.
Since you tried a JOIN, here the JOIN option:
SELECT
c.id, c.SalesPerson, c.Country,
c.Comment, c.uplodaed_datetime
FROM
CommentTable AS c
INNER JOIN
(SELECT
SalesPerson, Country,
MAX(uplodaed_datetime) AS uplodaed_datetime
FROM CommentTable
GROUP BY SalesPerson, Country) AS sub
ON c.SalesPerson = sub.SalesPerson
AND c.Country = sub.Country
AND c.uplodaed_datetime = sub.uplodaed_datetime
ORDER BY c.id;
Try out: db<>fiddle

SQL dividing a count from one table by a number from a different table

I am struggling with taking a Count() from one table and dividing it by a correlating number from a different table in Microsoft SQL Server.
Here is a fictional example of what I'm trying to do
Lets say I have a table of orders. One column in there is states.
I have a second table that has a column for states, and second column for each states population.
I'd like to find the order per population for each sate, but I have struggled to get my query right.
Here is what I have so far:
SELECT Orders.State, Count(*)/
(SELECT StatePopulations.Population FROM Orders INNER JOIN StatePopulations
on Orders.State = StatePopulations.State
WHERE Orders.state = StatePopulations.State )
FROM Orders INNER JOIN StatePopulations
ON Orders.state = StatePopulations.State
GROUP BY Orders.state
So far I'm contending with an error that says my sub query is returning multiple results for each state, but I'm newer to SQL and don't know how to overcome it.
If you really want a correlated sub-query, then this should do it...
(You don't need to join both table in either the inner or outer query, the correlation in the inner query's where clause does the 'join'.)
SELECT
Orders.state,
COUNT(*) / (SELECT population FROM StatePopulation WHERE state = Orders.state)
FROM
Orders
GROUP BY
Orders.state
Personally, I'd just join them and use MAX()...
SELECT
Orders.state,
COUNT(*) / MAX(StatePopulation.population)
FROM
Orders
INNER JOIN
StatePopulation
StatePopulation.state = Orders.state
GROUP BY
Orders.state
Or aggregate your orders before you join...
SELECT
Orders.state,
Orders.order_count / StatePopulation.population
FROM
(
SELECT
Orders.state,
COUNT(*) AS order_count
FROM
Orders
GROUP BY
Orders.state
)
Orders
INNER JOIN
StatePopulation
StatePopulation.state = Orders.state
(Please forgive typos and smelling pistakes, I'm doing this on a phone.)

Explanation of PostgreSQL Query

I'm having trouble unpacking this postgreSQL query:
select name, revenue from (
select facs.name, sum(case
when memid = 0 then slots * facs.guestcost
else slots * membercost
end) as revenue
from cd.bookings bks
inner join cd.facilities facs
on bks.facid = facs.facid
group by facs.name
) as agg where revenue < 1000
order by revenue;
Here are my questions.
the outer query is pulling "revenue" from the table returned by the inner query, which has a column name "revenue" as well. Is the outer query simply pulling the column from the inner query with this reference?
what is "as agg" doing in this query? It isn't referenced anywhere.
Yes. The outer query just references the value of "revenue" of the inner query which, in this case, is the result of the sum() function.
It's an alias for the result. If, for any reason, you want to use the result of your outer query, in another query, you reference it as 'agg'. For example, lets say I want to get the revenue < 500 of the initial result, I would create the following query:
SELECT revenue FROM agg WHERE revenue < 500
The inner query is querying the table 'bookings' (and naming it bks) it is joining the table 'facilities' (and naming it facs). The join is occurring on bookings.facid being equal to facilities.facid
The generated results of that join are being called "agg". There must be multiple entries with the same name in the 'facilities', as the results are grouped by facilities.'name'. 'revenue' is being calculated by the sum() function, which is calculating a total using all of the entries consisting of the same 'facilities'.'name'
"agg" is the name given to the results of inner query, as all generated results must be named, but does not need to be referenced in the outer query because 'name' and 'revenue' are unique in the outer query. So, "SELECT name, revenue" is the same as "SELECT agg.name, agg.revenue"
Read it like this
There is inner query which fetches you two columns name and revenew from joins
Below part is your revenew from bookings table
sum(case when memid = 0 then slots * facs.guestcost else slots * membercost end) as revenue
The booking table is then joined with facilities table like this
inner join cd.facilities facs on bks.facid = facs.facid
Since this is inner query so alias is must to give like agg
after when the inner query returns the data , the main select query
select name, revenue extracts the data <1000
the outer query is pulling "revenue" from the table returned by the inner query, which has a column name "revenue" as well. Is the outer query simply pulling the column from the inner query with this reference?
YES
what is "as agg" doing in this query? It isn't referenced anywhere.
its just an alias to tag that from as a table.

Transferring Data from one table to another

I need help with my sql code, is there a way for me to transfer the data from "AS subtotal" from the first SELECT statement to the "receipt.totalAmount" from the second SELECT statement. Kind of new with sql I tried to look it up online but I didn't see any solution for it. I can't declare subtotal from the first SELECT statement to the second SELECT statement. Also is it possible to sum up all the subtotals to the total column?
SELECT productServices.productId, productServices.proPrice, orders.orderId, orders.quantity, productServices.proPrice*orders.quantity AS subtotal , orders.dateOrdered
FROM productServices
JOIN orders
ON productServices.productId=orders.productId
SELECT receipt.receiptNo, receipt.customerId, receipt.orderId, receipt.employeeId, receipt.totalAmount, receipt.paymentMethod, receipt.dateOfPurchase
FROM receipt
JOIN customerInfo ON customerInfo.customerId=receipt.customerId
JOIN employeeInfo ON employeeInfo.employeeId=receipt.employeeId
JOIN orders ON orders.orderId=receipt.orderId
You need to write it into a single select statement. Something like this. Or use inner queries to get what you need.
SELECT receipt.receiptNo, receipt.customerId, receipt.orderId, receipt.employeeId, receipt.totalAmount, receipt.paymentMethod, receipt.dateOfPurchase,
productServices.productId, productServices.proPrice, orders.orderId, orders.quantity, productServices.proPrice*orders.quantity AS subtotal , orders.dateOrdered
FROM receipt
JOIN customerInfo ON customerInfo.customerId=receipt.customerId
JOIN employeeInfo ON employeeInfo.employeeId=receipt.employeeId
JOIN orders ON orders.orderId=receipt.orderId
JOIN productServices on productServices.productid = orders.productid

Sum Distinct Rows Only In Sql Server

I have four tables,in which First has one to many relation with rest of three tables named as (Second,Third,Fourth) respectively.I want to sum only Distinct Rows returned by select query.Here is my query, which i try so far.
select count(distinct First.Order_id) as [No.Of Orders],sum( First.Amount) as [Amount] from First
inner join Second on First.Order_id=Second.Order_id
inner join Third on Third.Order_id=Second.Order_id
inner join Fourth on Fourth.Order_id=Third.Order_id
The outcome of this query is :
No.Of Orders Amount
7 69
But this Amount should be 49,because the sum of First column Amount is 49,but due to inner join and one to many relationship,it calculate sum of also duplicate rows.How to avoid this.Kindly guide me
I think the problem is cartesian products in the joins (for a given id). You can solve this using row_number():
select count(t1234.Order_id) as [No.Of Orders], sum(t1234.Amount) as [Amount]
from (select First.*,
row_number() over (partition by First.Order_id order by First.Order_id) as seqnum
from First inner join
Second
on First.Order_id=Second.Order_id inner join
Third
on Third.Order_id=Second.Order_id inner join
Fourth
on Fourth.Order_id=Third.Order_id
) t1234
where seqnum = 1;
By the way, you could also express this using conditions in the where clause, because you appear to be using the joins only for filtering:
select count(First.Order_id) as [No.Of Orders], sum(First.Amount) as [Amount]
from First
where exists (select 1 from second where First.Order_id=Second.Order_id) and
exists (select 1 from third where First.Order_id=third.Order_id) and
exists (select 1 from fourth where First.Order_id=fourth.Order_id);