How to get the asked columns for each customers - sql

I have this table called table a
I need to get the CustomerID, sum(Income) of 2015, sum(Income) of 2016, did he ever bought productId A (boolean), is the total sum(income)> 1000 (boolean), number of total InvoiceID
all that in one query and the results should be with 1 row per customer.
please help I don't even know how to start!

This is basically conditional aggregation:
select customerid,
sum(case when extract(year from date) = 2015 then sales end) as sales_2015,
sum(case when extract(year from date) = 2016 then sales end) as sales_2016,
max( product = 'A' ) as ever_bought_a,
sum(income) > 1000 as sum_exceeds_1000,
count(*) as num_invoices
from t
group by customerid;
You haven't specified a database, so this is really psuedocode. You'll need to adapt it for your particular database.

Related

Combine different results of "group by" queries in the same table

I need to make some comparation between 2 years: sales by product, sales by category, etc.
How can I have this in one table having 3 columns:
first column = product, category, etc
second column = sales in 2021
third column = sales in 2022
Sample of queries that must be combined in one single table as the one below
select product_code, sum(amount)
from product
where year = '2021'
group by product_code
select product_code, sum(amount)
from product
where year = '2022'
group by product_code
select category_code, sum(amount)
from category
where year = '2021'
group by category_code
select category_code, sum(amount)
from category
where year = '2022'
group by category_code
Please, see the final table
[1]: https://i.stack.imgur.com/smF7h.png
NOTE!
If for instance in 2021 there was no "product D", it will be 0 for "Sales_2021" or the "product A" is no longer present in 2022, it will be 0 for "Sales_2022".
Thank you
You need two things here:
Conditional aggregation (a CASE expression inside the aggregation function) in order to get 2021 and 2022 in one go.
A union of two intermediate result sets (product figures UNION ALL category figures).
And as any table - and a query result is again a table - is unordered, we need an ORDER BY at last to get products first and categories second and also the products ordered alphabetically and the categories, too.
The complete query:
select category_or_product, sales_2021, sales_2022
from
(
select
product_code as category_or_product,
sum(case when year = 2021 then amount else 0 end) as sales_2021,
sum(case when year = 2021 then amount else 0 end) as sales_2022,
1 as product_first
from product
group by product_code
union all
select
category_code as category_or_product,
sum(case when year = 2021 then amount else 0 end) as sales_2021,
sum(case when year = 2021 then amount else 0 end) as sales_2022,
2 as product_first
from category
group by category_code
) unioned
order by product_first, category_or_product;

In SQL, how to you join multiple aggregate queries (count or sum specifically)?

I have a table that has the total number of different items per person. I am trying to create a new table that counts the number of people with a total of 0, 1, 2, 3, 4, 5, 6, and 7+ items grouped by company and year. I think I have individual queries that accomplish this task, but I can't get a join to work in order to fill the new table. The individual queries that seem to accomplish what I am trying to do are:
SELECT
Company,
YEAR(Date) as Year,
COUNT(*) as items0_Count
FROM table
WHERE items_total = 0
GROUP BY Company, YEAR(Date)
ORDER BY Company, YEAR(Date)
SELECT
Company,
YEAR(Date) as Year,
COUNT(*) as items1_Count
FROM table
WHERE items_total = 1
GROUP BY Company, YEAR(Date)
ORDER BY Company, YEAR(Date)
I would obviously have that same query 8 times with only the where statement changing in order to generate the counts for each case, but only included two here to keep the question short. Hope this makes sense, and thank you in advance for your help!
Use conditional aggregation:
SELECT Company, YEAR(Date) as Year,
SUM(CASE WHEN items_total = 0 THEN 1 ELSE 0 END) as items0_Count,
SUM(CASE WHEN items_total = 1 THEN 1 ELSE 0 END) as items2_Count
FROM table
GROUP BY Company, YEAR(Date)
ORDER BY Company, YEAR(Date);
You can add additional columns for whatever item counts you want.
Union all/ union the two queries you have. You'll get the desired else follow #GordonLinoff's answer.
Also as an easy way try this below
SELECT
Company,
YEAR(Date) as Year,
COUNT(*) as items0_Count
FROM table
WHERE items_total in (1,0)
GROUP BY Company, YEAR(Date)
ORDER BY Company, YEAR(Date)

SQL: Looking at Bundle of Products Sold

I have a sample DB below. I'm looking to see how many TV and Internet bundles we sold. In the sample data, only Bob and Trevor sold that bundle so we sold 2.
How do I write the query for the number of bundles sold by each Sales rep and the total price of the bundles sold?
Thanks
I imagine that, for a bundle to happen, the same sales person needs to have sold both products to the same customer.
I would approach this with two levels of aggregation. First group by sales person and customer in a subquery to identify the bundles, then, in an outer query, count how many such bundles happened for each sales person:
SELECT sales_person, COUNT(*) bundles_sold, SUM(total_price) total_price
FROM (
SELECT sales_person, customer_name, SUM(total_price) total_price
FROM mytable
WHERE product_name in ('TV', 'Phone')
GROUP BY sales_person
HAVING COUNT(DISTINCT product_name) = 2
) x
You can simply group the salesman's by counting the distinct products they sold -
SELECT Sales_Person, FLOOR(COUNT(DISTINCT product_name)/2) NO_OF_BUNDLES, sum(total_price)
FROM YOUR_TAB
WHERE product_name IN ('TV', 'Internet')
GROUP BY Sales_Person
HAVING COUNT(DISTINCT product_name) >= 2
Using cte as below:
with cte1(sales_person, customer_name, product_count) as
(
select sales_person, customer_name, count(product_name)
from sales
where product_name in ('TV', 'Internet')
group by sales_person, customer_name
having count(product_name) = 2
)
select sales_person, count(product_count)
from cte1
group by sales_person
I would suggest two levels of aggregation:
select sales_person, count(*), sum(total_price)
from (select sales_person, customer_name,
sum(total_price) as total_price,
max(case when product_name = 'tv' then 1 else 0 end) as has_tv,
max(case when product_name = 'phone' then 1 else 0 end) as has_phone,
max(case when product_name = 'internet' then 1 else 0 end) as has_internet
from t
group by sales_person, customer_name
) sc
where has_phone = 0 and
has_tv = 1 and
has_internet = 1
group by sales_person;
I recommend this structure because it is pretty easy to change the conditions in the where clause to return this for any bundle -- or even to aggregate by the three flags and return the totals for all bundles in one query.

SQL: calculate value based on two different conditions

Below is my table schema:- Appointments
--------------------------------------
| schID | appointment_date | amount | location |
--------------------------------------
I want to fire a single query where I can get the sum of amount, total appointment_date this year i.e 2016 and remaining appointment_date this year i.e 2016.
So I wrote the below query to calculate the above fields:-
SELECT sum(a.amount) as total,
count(distinct a.appointment_date) as total_appointment,
count(distinct a2.appointment_date) as remaining appointments
from Appointments a
LEFT JOIN Appointments a2 ON a.schID = a2.schID
WHERE a2.appointment_date > GETDATE() AND year(a.appointment_date) = 2016
group by a.location
The above query doesnt return value as per requirement :(
The database belongs to SQL Server.
You can use conditional aggregation for this:
SELECT sum(amount) as total,
count(appointment_date) as total_appointment,
count(DISTINCT CASE
WHEN appointment_date > GETDATE() AND YEAR(appointment_date) = 2016
THEN DATE(appointment_date)
END) as remaining appointments
from Appointments a
group by a.location
You shouldn't need a join for this type of query:
SELECT sum(a.amount) as total, count(a.appointment_date) as total_appointment,
sum(case when a.appointment_date > getdate() then 1 else 0
end) as remaining appointments
from Appointments a
where year(a.appointment_date) = year(GETDATE() );
If you need the breakdown by location, then include location in both the select and group by clauses.

adding a calculated/virtual column to an existing query

My query returns a sales column total for each month and a purchases total for each month, for certain categories.
SELECT theMonth,
sum(Sales) as sumSales,
sum(Saleswotax) as sumSaleswotax,
sum(Purchases) as sumPurchases,
sum(Purchaseswotax) as sumPurchaseswotax
FROM ( SELECT date_format(saledate, '%Y-%m') AS theMonth,
sales.cost as Sales,
ROUND(sales.cost*0.85, 2) AS Saleswotax,
0 AS Purchases,
0 AS Purchaseswotax
FROM sales, products
WHERE sales.product = products.name
AND category='Food'
UNION ALL
SELECT date_format(purchasedate, '%Y-%m') AS theMonth,
0 as Sales,
0 AS Saleswotax,
purchases.cost as Purchases,
ROUND(purchases.cost*0.85, 2) AS Purchaseswotax,
FROM purchases) AS all_costs
group by theMonth
I am trying to return a column(that does not actually exist in the table) in my query that is just a calculation of an existing table., ie the saleswotax and purchaseswotax columns.
I am using a function, and returning it AS a name...why is it not working?
In the union, you used 0 as sales and purchases columns, but didn't also do that for -wotax columns. They need to match up for the union to work properly (I think you know that, since you did it for Sales and Purchases).
You need to remove the comma after AS Purchasewotax in the latter half of the UNION:
SELECT theMonth,
sum(Sales) as sumSales,
sum(Saleswotax) as sumSaleswotax,
sum(Purchases) as sumPurchases,
sum(Purchaseswotax) as sumPurchaseswotax
FROM ( SELECT date_format(saledate, '%Y-%m') AS theMonth,
sales.cost as Sales,
ROUND(sales.cost*0.85, 2) AS Saleswotax,
0 AS Purchases,
0 AS Purchaseswotax
FROM sales, products
WHERE sales.product = products.name
AND category='Food'
UNION ALL
SELECT date_format(purchasedate, '%Y-%m') AS theMonth,
0 as Sales,
0 AS Saleswotax,
purchases.cost as Purchases,
ROUND(purchases.cost*0.85, 2) AS Purchaseswotax
FROM purchases) AS all_costs
GROUP BY theMonth
Last time when I saw, there was no declarative support for computed fields in MySQL.
You would have to either add computed columns to your table and fill them using an UPDATE/INSERT trigger. Or create Views with additional computed columns.