Sql join only on the first match - sql

I don't know how to perform the the following case.
I have the sales info in a table:
Number of Bill (key),
Internal number (key),
Client,
Date (month-year),
Product group,
Product,
Quantities,
Total,
Sales man.
I need to joint this sales tables with the annual forecast sales table that is the next one:
Date (key),
Group product(key),
Sales man (key),
Total.
In each tables the combination of the key is the primary key. I need to add in the sales tables the forecast. For this I need to add the sales of the forecast in the real sale only on the first match of date, group product and sales man, so the total of forecast sales don't get bigger than it is (a sales man can sell the same group product, to the same client, in the same day on multiple times).

.. only on the first match of date, group product and sales man ..
You can use window functions for this, consider using ROW_NUMBER() OVER(PARTITION BY ... ORDER BY ... ). First match has row number of 1.
More information and examples (sales!) can be found from MSDN.

Related

SQL QUERY for sum loans per customer

enter image description here
I need a query that returns all customers whose name contains the string "Will", and their associated total loan values.
Loan totals should be sorted from largest amount to smallest amount and the loans totals column should be called "TotalLoanValue".
Only one record per customer should be returned.
SELECT name, loan_amount
FROM customers, loans
WHERE name LIKE '%WILL%'
I have wrote that query, but I'm having a hard time to figure out how to sum all the loan values per customer
To say first things first:
If you want to ask further questions here, you should please read and follow this: How to create a good example instead of just adding a link.
Otherwise, you will be on risk that your questions will just be closed and you will never get an answer.
To answer your question:
We need to JOIN the two tables by their common column and then build the SUM of all loan amounts with a GROUP BY clause of the customer name.
I didn't follow your link because I wouldn't know if this is spam, so let's say the customer table has a column "id" and the loan table a column "customer_id".
Then your query will look like this:
SELECT c.name, SUM(l.loan_amount)
FROM customers c
JOIN loan l
ON c.id = l.customer_id
WHERE c.name LIKE '%will%'
GROUP BY c.name
ORDER BY SUM(l.loan_amount) DESC, c.name;
The ORDER BY clause makes sure to begin with the customer having the highest sum of loan amounts.
The "c.name" at the end of the ORDER BY clause could be removed if we don't care about the order if different customers have the same sum of loan amounts.
Otherwise, if we use the query as shown, the result will be sorted by the sum of loan amounts first and then with a second priority by the customer name, i.e. will sort customers having the identic sum of loan amounts by their name.
Try out with some sample data here: db<>fiddle

How do I use array_agg with a condition?

I have a table with a list of potential customers, their activity, and their sales representative. Every customer can have up to 1 sales rep. I've built a summary table where I aggregate the customer activity, and group it by the sales rep, and filter by the customer creation date. This is NOT a cohort (the customers do not all correspond to the scheduled_flights, but rather this is a snapshot of activity for a given period of time) It looks something like this:
Now, in addition to the total number of customers, I'd also like to output an array of those actual customers. The customers field is currently calculated by performing sum(is_customer) as customers and then grouping by the sales rep. To build the array, I've tried to do array_agg(customer_name) which outputs the list of all customer names -- I just need the list of names who also satisfy the condition that is_customer = 1, but I can't use that as a where clause since it would filter out other activity, like scheduled and completed flights for customers that were not new.
This should probably work:
array_agg(case when is_customer = 1 then customer_name end) within group (order by customer_name)
Snowflake should ignore NULL values in the aggregation.

Partitions and groupby: first quarter with company sales

I have a table with company sales by quarter. The table only registers transactions that occurred, so if there are no sales in a given quarter, it won't appear at all in the table.
I would like to find the first quarter that the company has any sales.
If I include group by 1, I get error: 'quarter' is not present in the GROUP BY list. If I don't include it, I get duplicate rows. What is the correct syntax to get just one row associated with each company?
select
company,
first_value(quarter) over (partition by company order by year_quarter) as first_quarter
from
sales_table
group by 1

SQL to find the average amount of money spent by country?

I need to find the average amount of money spent by country, using the two tables below in oracle. Sale_total is the money spent in each sale and Cust_country is the customer's country. Any help would be greatly appreciated.
Tables
Sale
Sale_Id
Payment_ID
Ship_Id
Customer_ID
Sale_total ==> Money Spent
Sale_date
Sale_time
Customer
Cust_name
Cust_address
Cust_city
Cust_country
Cust_phone
Cust_age
Cust_sex
You need to have a link between the Sale and Customer tables. Presumably place Customer_ID in the Customer table as a primary key, and have Customer_ID in the Sale table be a foreign key. Assuming you do that, you can then run the below query.
SELECT
AVG(S.Sale_Total) Spent,
c.Cust_country
FROM
Sale S
INNER JOIN
Customer C on S.Customer_ID=C.Customer_ID
GROUP BY C.Cust_Country
This tells you the average amount spent, and the country where it was spent.
The key to understanding this answer is that AVG (the average function) is an aggregate function, as it combines things. Often when you have an aggregate function, you have to group the other columns, hence why we included the GROUP BY clause.
The reason you need Customer Id in the Customer table (apart from being the logical place for it) is so that you can establish a relationship between the Customer and Sale tables.
Another way to establish the relation is you can create a new table to link Customer and Sale together. Call it Customer Sales. For example:
Customer_Sales
Customer_Id
Sale_Id
Then you'd adjust the query to join based on that.
Try this:
SELECT C.Cust_country as Country, AVG(S.Sale_total) as Spent
FROM Sale S INNER JOIN
Customer C on S.Customer_ID=C.Customer_ID
GROUP BY C.Cust_country
AVG is an aggregate function that evaluates the average of an expression over a set of rows.
Read more about here.

grouping common results in sql

I have a products table, with the fields product, category and cost, of type varchar, varchar and decimal.
I then have a sales table, with the fields client, productname, quantity, cost, and saledate, of type varchar, varchar, int, decimal and date.
I want to show all of the products sold for a month, say the current month.
However, I donĀ“t want to show every sale individually. I want to automatically add all of one product together and show it as one row.
In the sales table, the cost for each sales record is already multiplied by the quantity.
So for example, to if 5 beers were purchased, it would returned as one row showing name as beers, quanity as 5, and cost as however much.
I need something like say:
Select product, cost from sales, WHERE sales.product=products.name
AND category='food' AND WHERE month(date_field) = month(getdate())
This should show all the sales for a certain category of product for the current month, but is there an easy way to "group" products together?
I would have to take into account the quantity field in the sales table, because one sale is not necessarily only one product
A hopefully clearer example, one sale record maybe for 2 beers for one client with a cost of 10, and another sales record may be to a different client with a quantity of 3 and cost of 15. I want just one record that would say for beer, 5 were sold and the total cost is 25.
I have no idea where to go from as far as I have gotten...
You are looking for something like
Select product, cost from sales,products WHERE sales.product=products.name
AND category='food' AND month(date_field) = month(getdate())
To get a listing of the items linked as you suggest according to the category in the products tables.
To get the summary by category you need something like:
Select category,SUM(Sales.Quantity),SUM(Sales.cost) from
sales,products WHERE sales.product=products.name
AND category='food' AND month(date_field) = month(getdate()) group by category
This will work but there is a lot to criticise in your database structure, specifically to link products by name as you do is not very reliable.
This question looks awfully familiar...
The answer is a SQL GROUP BY statement.
SELECT product, SUM(quantity) FROM sales s, products p WHERE product=p.name AND category='food' AND month(date_field)=month(getdate()) GROUP BY product
The SUM(quantity) above will tally up all the units sold of a particular product in the given month.
Use GROUP BY and COUNT
SELECT productname, cost, COUNT(*) AS cnt
FROM sales LEFT JOIN products ON sales.product = products.productname
WHERE category='food' AND month(date_field) = month(getdate())
GROUP BY productname