SQL Server INNER JOIN and GROUP BY - sql

In sql server I'm trying to group by each sales people some infos as follow:
I have 2 tables: Positions and Clients
In Positions table, I have the following columns: Client_Id, Balance, Acquisition_Cost and in the Clients table I use the following columns: Client_Id and Sales_person.
I want to group by Sales_person (Clients table) the Client_id, Balance, Acquisition_Cost (Positions table)
I tried this:
SELECT Positions.Client_ID, Positions.Balance, Positions.Acquisition_cost
FROM Positions
INNER JOIN Clients ON Positions.Client_ID = Clients.Client_ID
GROUP BY Sales_person
It gives me "Positions.Client_ID is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause".
I precise I'm pretty new on SQL so that does not ring that much a bell to me.

You need to add Positions.Client_ID in the GROUP BY Clause, since the select expects this column if you really do not want Positions.Client_ID in the select, then no need to add in the GROUP BY Clause

For any column in your SELECT that you aren't including in the GROUP BY, you need to use some kind of aggregate function (MAX, SUM, etc.) on the column. So you could write it like this:
SELECT Positions.Client_ID
, Clients.Sales_person
, SUM(Positions.Balance) Balance_Sum,
, SUM(Positions.Acquisition_cost) Acquisition_Cost_Sum
FROM Positions
INNER JOIN Clients ON Positions.Client_ID = Clients.Client_ID
GROUP BY Positions.Client_ID
, Clients.Sales_person
If you only want the totals by Sales_person and not client_ID, you could just remove client_id from the SELECT AND GROUP BY:
SELECT Clients.Sales_person
, SUM(Positions.Balance) Balance_Sum,
, SUM(Positions.Acquisition_cost) Acquisition_Cost_Sum
FROM Positions
INNER JOIN Clients ON Positions.Client_ID = Clients.Client_ID
GROUP BY Clients.Sales_person

SELECT a.Client_ID, b.Sales_person, SUM(a.Balance) as Balance_Sum,SUM(a.Acquisition_cost) as Acquisition_Cost_Sum FROM Positions as a INNER JOIN Clients as b ON a.Client_ID = b.Client_ID GROUP BY a.Client_ID, b.Sales_person

Thanks all of you guys, here's the code that works for me in this case:
SELECT Positions.Client_Id, Clients.Sales_person, SUM(Positions.Balance) as sum_balance_impacted, SUM(Positions.Acquisition_cost) as sum_acquisition_cost
FROM Positions
INNER JOIN Clients ON Positions.Client_Id= Clients.Client_Id
GROUP BY Clients.Sales_person, Positions.Client_Id```

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

Oracle SQL sum transactions by distinct customer id

I need to select the sum of transaction columns, count # of transactions, all by distinct customer ids. I have tried a few nested queries as well as something like the following:
select distinct(customer_id), sum(tran_amt), count(tran)
from tran_table
inner join tender_table;
The tender_table has the customer id so I have to join it.
You are using group functions, but you don't have a "group by" clause, I think this will give you the correct answer:
SELECT customer_id, SUM(tran_amt), COUNT(tran)
FROM tran_table INNER JOIN tender_table
GROUP BY CUSTOMER_ID;
I am guessing you want something like this:
select te.customer_id, sum(t.tran_amt), count(*)
from tran_table t inner join
tender_table te
on t.?? = te.??
group by te.customer_id;
You need join conditions and a group by clause. The ?? is for the columns used for the join, which your question does not specify.
Try this :
select tb_tran.customer_id, sum(tran_amt), count(tran)
from tran_table tb_tran inner join tender_table tb_tender
on tb_tran.customer_id = tb_tender.customer_id
group by tb_tran.customer_id;

Oracle SQL using group by: Can you group by a field used to join two tables?

SELECT b.first_name, b.last_name, SUM(t.price_total)
FROM brokers b
LEFT OUTER JOIN
trades t
ON b.broker_id=t.broker_id
GROUP BY
b.broker_id
My problem question asks to 'Display the total value of each broker's trades'. The answer groups by b.first_name||' '||b.last_name, but I think the group by should be done via the broker's ID (i.e. two people with the same name could be grouped together, this wouldn't happen via broker id).
yet when running my code, i get an error
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
Error at Line: 1 Column: 8
my question is, why can't I use b.broker_id as the only column to group by?
Just add last_name and first_name in GROUP BY
SELECT b.first_name, b.last_name, SUM(t.price_total)
FROM brokers b
LEFT OUTER JOIN
trades t
ON b.broker_id=t.broker_id
GROUP BY
b.broker_id,b.first_name, b.last_name
If two people have the same last and first names, it will be different rows in the result because of broker_id in GROUP BY
It's because you are including b.first_name and b.last_name in your select clause, without either aggregating them or grouping by them.
You can either add both items to the group by clause, or use an aggregation function (such as max) on each of them in the select clause, to make your query work.
A slightly different approach is to group the trades by broker ID, then join the result of that to the brokers table:
SELECT b.first_name, b.last_name, price_sum
FROM brokers b
LEFT OUTER JOIN (
SELECT broker_id, SUM(price_total) AS price_sum
FROM trades
GROUP BY broker_id
) t
ON b.broker_id=t.broker_id
Personally I feel like this expresses more clearly what you are trying to do.
try this:
SELECT b.broker_id, b.first_name, b.last_name, SUM(t.price_total)
FROM brokers b
LEFT OUTER JOIN
trades t
ON b.broker_id=t.broker_id
GROUP BY
b.broker_id, b.first_name, b.last_name
When you use GROUP BY, select clause can have only the columns specified in GROUP BY and aggregated/calculated fields for that group like sum, average, min, max etc.
You can use analytic functions to overcome it, this is mainly used to avoid self joins and get the all the fields you require while doing aggregations:
SELECT distinct * from (SELECT b.first_name, b.last_name,
SUM(t.price_total) over (partition by b.broker_id) price_total
FROM brokers b
LEFT OUTER JOIN
trades t
ON b.broker_id=t.broker_id);
Try to change your GROUP BY clause into:
...
GROUP BY b.first_name, b.last_name

SQL Server Grouping issue

I have two tables.
Customer ID, NAME, MonthlyIncome
Orders ID, CustomerKey, TotalCost
I want join those two table into one, in the way that having total amount the bought in the shop.
CustomerKey, MonthlyIncome, TotalCost.
I have tried to group by CustomerKey, but I am not able to include the rest of the columns. Which query should I be using?
SELECT
fs.CustomerKey, SUM(fs.TotalCost) as TotalBought
FROM
FactOnlineSales fs
INNER JOIN
DimCustomer c on c.CustomerKey = fs.CustomerKey
GROUP BY
fs.CustomerKey
I have tried to group by CustomerKey, but not able to manage how to include rest of the columns.
Just do it:
SELECT fs.CustomerKey,
c.MonthlyIncome,
SUM(fs.TotalCost) as TotalBought
FROM FactOnlineSales fs
INNER JOIN DimCustomer c
ON c.CustomerKey = fs.CustomerKey
GROUP BY fs.CustomerKey,
c.MonthlyIncome
Presumably CustomerKey is unique, so grouping by a less unique column isn't going to change the SUM total.
You didn't mention what version of SQL Server you're using - but if you're on SQL Server 2005 or newer, you could use the OVER() clause:
SELECT
fs.CustomerKey,
c.MonthlyIncome,
TotalBought = SUM(fs.TotalCost) OVER(PARTITION BY fs.CustomerKey)
FROM
FactOnlineSales fs
INNER JOIN
DimCustomer c on c.CustomerKey = fs.CustomerKey
That basically gives you the CustomerKey, the MonthlyIncome and then sums the TotalCost for each CustomerKey and displays the appropriate value in your output. No need to do a GROUP BY in this case
You may have an error in the ON clause of the join.
You used CustomerKey instead of Customer ID from the DimCustomer table.
For gouping: you must group by every column you don't aggregate on, so you can include NAME (so you can have descriptive customer) and MonthlyIncome.
SELECT
c."Customer ID",
c.NAME,
c.MonthlyIncome,
SUM(fs.TotalCost) as TotalBought
FROM
FactOnlineSales fs INNER JOIN DimCustomer c
on c."Customer ID" = fs.CustomerKey
GROUP BY
c."Customer ID",
c.NAME,
c.MonthlyIncome

sql multiple count

I have 3 tables, where the first one's primary key, is the foreign key in the other 2.
I want to extract one field from the first table, and then a count from the other 2, all joined using the pk and fk. This is what I have so far:
SELECT MBDDX_STUDY.STUDY_NAME, COUNT(MBDDX_EXPERIMENT.STUDY_ID) AS NUMBER_OF_EXPERIMENTS
FROM MBDDX_STUDY
INNER JOIN MBDDX_EXPERIMENT
ON MBDDX_STUDY.ID=MBDDX_EXPERIMENT.STUDY_ID
INNER JOIN (SELECT COUNT(MBDDX_TREATMENT_GROUP.GROUP_NO) AS NUMBER_OF_GROUPS
FROM MBDDX_TREATMENT_GROUP)
ON MBDDX_TREATMENT_GROUP.STUDY_ID = MBDDX_STUDY.ID
group by MBDDX_STUDY.STUDY_NAME, MBDDX_TREATMENT_GROUP.STUDY_ID
But, i get an error saying that the MBDDX_TREATMENT_GROUP.STUDY_ID , in the penultimate line is an invalid indentifier. It is a correct table.
Any advise please.
Thanks.
You're getting the error because that column is not in your SELECT, so it can't GROUP BY a field it doesn't have.
The subquery syntax doesn't seem to make any sense to me. You've made a query that counts all rows of MBDDX_TREATMENT_GROUP, independently of the STUDY_ID, and then tries to join it into the table with a join condition that doesn't refer to anything in the subquery's results (and can't, without an alias).
Why not use a simple join? Assuming MBDDX_EXPERIMENT also has a primary key ID, you can do it with a COUNT-DISTINCT:
SELECT
MBDDX_STUDY.ID, MBDDX_STUDY.STUDY_NAME,
COUNT(DISTINCT MBDDX_EXPERIMENT.ID) AS NUMBER_OF_EXPERIMENTS
COUNT(DISTINCT MBDDX_TREATMENT_GROUP.GROUP_NO) AS NUMBER_OF_GROUPS
FROM
MBDDX_STUDY
INNER JOIN MBDDX_EXPERIMENT ON MBDDX_EXPERIMENT.STUDY_ID=MBDDX_STUDY.ID
INNER JOIN MBDDX_TREATMENT_GROUP ON MBDDX_TREATMENT_GROUP.STUDY_ID=MBDDX_STUDY.ID
GROUP BY
MBDDX_STUDY.ID, MBDDX_STUDY.STUDY_NAME
(MBDDX_STUDY.STUDY_NAME technically shouldn't be necessary to include in the GROUP BY expression according to ANSI SQL as it has a functional dependency on STUDY_ID. However it is necessary on Oracle, which can't spot the dependency.)
You don't need to group by this field (MBDDX_TREATMENT_GROUP.STUDY_ID). It should be just group by MBDDX_STUDY.STUDY_NAME
If my understanding is correct,You need a record from first table and have the count of related records in the other two tables.Here is the answer
SQL:Getting count from many tables for a user record in USER table.Whats the best approach?
It looks like you need to alias the second subquery and need to include something to join on.
It also looks like you aren't using the count you have in the subquery as well.
Try this out:
SELECT MBDDX_STUDY.STUDY_NAME
, COUNT(MBDDX_EXPERIMENT.STUDY_ID) AS NUMBER_OF_EXPERIMENTS
FROM MBDDX_STUDY
INNER JOIN MBDDX_EXPERIMENT
ON MBDDX_STUDY.ID=MBDDX_EXPERIMENT.STUDY_ID
INNER JOIN (SELECT STUDY_ID, COUNT(MBDDX_TREATMENT_GROUP.GROUP_NO) AS NUMBER_OF_GROUPS
FROM MBDDX_TREATMENT_GROUP GROUP BY MBDDX_TREATMENT_GROUP.STUDY_ID) xx
ON xx.STUDY_ID = MBDDX_STUDY.ID
GROUP BY MBDDX_STUDY.STUDY_NAME, xx.STUDY_ID
For what you really want to do, you want OUTER JOINs.
WITH number_of_experiments
AS ( SELECT study_id
, count ( * ) CNT
FROM MBDDX_EXPERIMENT
group by study_id )
, number_of_groups
as ( select study_id
, count ( * ) CNT
FROM mbddx_treatment_group
group by study_id )
select study_name
, coalesce(noex.cnt,0)
, coalesce(notr.cnt,0)
from mbddx_study
outer join number_of_experiments
as noex
using ( study_id )
outer join number_of_groups
as nogr
using ( study_id )