SQL: Fetching total shares of a customer through multiple tables - sql

I have 3 tables customer(cid, name, phone) and transactions (cid (reference), fundid, date, shares) and fund (fundid, fund_name).
I am trying to write an sql query that would get me the total number of shares for each customer for each fund.
Here are the sample inserts:
INSERT INTO CUSTOMER(1, 'Alex', '123456678');
INSERT INTO CUSTOMER(2, 'Bill', '6323450236');
INSERT INTO CUSTOMER(3, 'Marie', '8568289912');
INSERT INTO FUND (1, 'Docotel');
INSERT INTO FUND (2, 'Armen');
INSERT INTO FUND (3, 'TD');
INSERT INTO TRANSACTIONS(1, 2, '2010-2-12', 234); (means shares bought)
INSERT INTO TRANSACTIONS(3, 1, '2010-4-2', 192);
INSERT INTO TRANSACTIONS(1, 2, '2010-4-22', -45); (the '-' means shares sold)
INSERT INTO TRANSACTIONS(1, 3, '2010-4-26', 220);
INSERT INTO TRANSACTIONS(3, 2, '2010-7-21', 170);
I want the sql result to look something like this:
Name| Fund_Name | Total_Shares |
Alex Docotel 189
Alex TD 220
Marie Docotel 192
Marie Armen 170
Thanks

Try this:
SELECT customer.name, fund.fund_name, T1.total_shares
FROM
(
SELECT cid, fundid, SUM(shares) AS total_shares
FROM transactions
GROUP BY cid, fundid
) T1
JOIN customer ON T1.cid = customer.cid
JOIN fund ON T1.fundid = fund.fundid
ORDER BY customer.name

Related

sql add columns in group dynamically

It is necessary to build a summary table based on data about the customer and their payments, where the columns will be the sequential number of the contract (contact_number) and the year (year) grouped by gender. The main condition is that contact_number and year should be dynamically generated.
Test data:
CREATE TABLE loans
(
loan_id int,
client_id int,
loan_date date
);
CREATE TABLE clients
(
client_id int,
client_name varchar(20),
gender varchar(20)
);
INSERT INTO CLIENTS
VALUES (1, arnold, 'male'),
(2, lilly, 'female'),
(3, betty, 'female'),
(4, tom, 'male'),
(5, jim, 'male');
INSERT INTO loans
VALUES (1, 1, '20220522'),
(2, 2, '20220522'),
(3, 3, '20220525'),
(4, 4, '20220525'),
(5, 1, '20220527'),
(6, 2, '20220527'),
(7, 3, '20220601'),
(8, 1, '20220603'),
(9, 2, '20220603'),
(10, 1, '20220603');
Formation of columns can be done using the case when construct, but this option is not suitable due to the need to constantly add new lines in the query when adding data.
My code:
with cte as
(
select
l.client_id,
loan_date,
extract(year from loan_date) as year,
client_name,
gender,
row_number() over (partition by l.client_id order by loan_date asc) as serial_number_contact
from
loans l
inner join
client c on l.client_id = c.client_id
)
select
gender
, year
, contract_number
, count(*)
from cte
group by gender, year, contract_number
order by year, contract_number
expected Output :
sex
1 contract, 2022
2 contract, 2022
3 contract, 2022
male
2
2
1
female
4
1
1
RDMBS - postgres

sql select sum conditions

I'm studying sql (by myself) and I would like to know how I would do for these examples:
1- i'd create this 3 tables bellow:
CREATE TABLE Business (
Id INT,
Category INT,
Business_Name VARCHAR(30),
City_Id INT,
Billing INT
);
INSERT INTO business (Id, Category, Business_Name, City_Id, Billing) VALUES(1, 1, 'Bread', 1, 50);
INSERT INTO business (Id, Category, Business_Name, City_Id, Billing) VALUES(2, 2, 'Oreo', 2, 10);
INSERT INTO business (Id, Category, Business_Name, City_Id, Billing) VALUES(3, 2, 'Pizza', 3, 15);
INSERT INTO business (Id, Category, Business_Name, City_Id, Billing) VALUES(4, 2, 'Beer', 4, 25);
INSERT INTO business (Id, Category, Business_Name, City_Id, Billing) VALUES(5, 1, 'Steak', 1, 80);
CREATE TABLE City (
Id INT,
City_Name VARCHAR(30)
);
INSERT INTO City (Id, City_Name) VALUES(1, 'Paris');
INSERT INTO City (Id, City_Name) VALUES(2, 'New York');
INSERT INTO City (Id, City_Name) VALUES(3, 'Tokio');
INSERT INTO City (Id, City_Name) VALUES(4, 'Vancouver');
INSERT INTO City (Id, City_Name) VALUES(5, 'Cairo');
CREATE TABLE Category (
Id INT,
Category_Name VARCHAR(30)
);
INSERT INTO Category (Id, Category_Name) VALUES(1, 'Bar');
INSERT INTO Category (Id, Category_Name) VALUES(2, 'Pub');
INSERT INTO Category (Id, Category_Name) VALUES(3, 'Pizza');
2- I want to make these SQL queries:
a) Total Value of Billing (Billing) all stores, like this table:
-----------------------
|Business_Name | Total |
|--------------+-------|
|Total | 180 |
------------------------
b) All Total Billing by Category_Name like this table:
-------------------
|Category | Total |
|---------+-------|
|Bar | 130 |
|---------+-------|
|Pub | 50 |
|---------+-------|
|Pizza | 5 |
----------+--------
c)List the Business_Name with min billing, showing the: Category_Name, Business_Name, and Billing like this table:
----------------------------------------
|Category_Name | Business_Name | Total |
|--------------+---------------+-------|
|Pub | Beer | 5 |
|--------------+---------------+--------
d) All Total of Billing by City, showing the: Category_Name, Business_Name, City_Name and Billing like this table
--------------------------
|City | Total |
|----------------+-------|
|Cairo | 0 |
|----------------+-------|
|New York | 10 |
|----------------+-------|
|Paris | 130 |
|----------------+-------|
|Tokio | 15 |
-----------------+--------
|Vancouver | 25 |
-----------------+--------
Any body with a little more knowledge that could be help me, please? =)
First thing is first, all of these are basic queries and i have to point out that a simple google search for tutorials(ex1, ex2, ex3) would have answered most of these. as we are here to provide help and guidance i hope you take it to heart and read the tutorials before going over the answers.
with that said to be able to help you out i will walk through each query and provide an overview of what is happening.
a) you need an aggregate operation here to sum up the values. You would use the sum key word. normally you need a group by, but in this case since we only have a hard coded column with the word "Total" in it, it is not required. we also give each of the columns an alias as per your table. this is after the column name.
select 'Total' as business_Name,
sum(billing) Total
from business
b) This one is almost an exact copy of a, but requires a grouping. in this case you have to use the group by key word for all columns that are not in aggregates. in this case it is only the category name. it is good practice to not use the ordinal position in group by and order by statements, you should always spell out the columns you are using when able.
select c.category_name,
sum(billing) total
from business b
inner join category c
on b.category = c.id
group by c.category_name
c) We continue to build onto the query and add another column in the select statement and then add a column to the group by to allow grouping.
select c.category_name,
b.business_name,
sum(billing) total
from business b
inner join category c
on b.category = c.id
group by c.category_name, b.business_name
d) For this query its very similar to b, but instead of category_name we do a join on city with city id.
select c.city_name
,sum(billing) as total
from business b
inner join city c on c.id = b.city_id
group by c.city_name
with all of this said, several of your examples do not match your expected output. but these queries do match the expected output with the data you provided.
I really do recommend going through some tutorials to grasp the basics of sql better.
Here is answer to one of the queries. But I'd recommend you to read online basic sql tutorials and you will be able to write them yourself easily.
b)
select c.category_name
,sum(billing)
from business b
join category c
on b.category = c.id
group by 1

How to Get Sum of One Column Based On Other Table in Sql Server

I have 2 table in my database (like this):
tblCustomers:
id CustomerName
1 aaa
2 bbb
3 ccc
4 ddd
5 eee
6 fff
tblPurchases:
id CustomerID Price
1 1 300
2 2 100
3 3 500
4 1 150
5 4 50
6 3 250
7 6 700
8 2 30
9 1 310
10 4 25
Now I want with "Stored Procedures" take a new table that give me the sum of price for each customer. Exactly like under.
How can do that?
Procedures Result:
id CustomerName SumPrice
1 aaa 760
2 bbb 130
3 ccc 750
4 ddd 75
5 eee 0
6 fff 700
select c.id, c.customername, sum(isnull(p.price, 0)) as sumprice
from tblcustomers c
left join tblpurchases p
on c.id = p.customerid
group by c.id, c.customername
SQL Fiddle test: http://sqlfiddle.com/#!3/9b573/1/0
Note the need for an outer join because your desired result includes customers with no purchases.
You can use the below query to get the result
select id,CustomerName,sum(price) as TotalPrice
from
(
select tc.id,tc.CustomerName,tp.price
from tblCustomers tc
join
tblPurchases tp on tc.id = tp.CustomerID
) tab
group by id,CustomerName
Although the other answers here do work, they don't appear to be what I would consider standard practice, or optimal.
The simplest solution (standard, but not always optimal) requires no sub-query of any variety.
SELECT
cust.id,
cust.CustomerName,
SUM(prch.price) AS SumPrice
FROM
tblCustomers AS cust
INNER JOIN
tblPurchases AS prch
ON cust.id = prch.CustomerID
GROUP BY
cust.id,
cust.CustomerName
The only reason that this is not necessarily optimal is that it involves grouping by two fields, one of which is a string. This involves creating 'counters' in memory that are identified by this composite of an id and string, which can be inefficient due to the fact that you only really need to use the id to uniquely identify the counter. (The identifier is only one item and is a small (probably only 4 bytes), rather than multiple items one of which is long (potentially many many bytes)).
This means that you can do the following as a possible optimisation. Though depending on your data this many be a premature optimsation, it has no performance down-side and is always good to know about...
SELECT
cust.id,
cust.CustomerName,
prch.SumPrice
FROM
tblCustomers AS cust
INNER JOIN
(
SELECT
CustomerID,
SUM(price) AS SumPrice
FROM
tblPurchases
GROUP BY
CustomerID
) AS prch
ON cust.id = prch.CustomerID
This makes the in-memory aggregation as simple as possible, as so as quick as possible.
In both cases you should have the best possible efficiency in the query by ensuring that you have indexes on tblCustomer(id) and on tblPurchases(CustomerID),
DECLARE #tblcustomers table (id int, customername varchar(10));
insert into #tblcustomers values (1, 'aaa');
insert into #tblcustomers values (2, 'bbb');
insert into #tblcustomers values (3, 'ccc');
insert into #tblcustomers values (4, 'ddd');
insert into #tblcustomers values (5, 'eee');
insert into #tblcustomers values (6, 'fff');
DECLARE #tblpurchases table (id int, customerid int, price int);
insert into #tblpurchases values (1, 1, 300);
insert into #tblpurchases values (2, 2, 100);
insert into #tblpurchases values (3, 3, 500);
insert into #tblpurchases values (4, 1, 150);
insert into #tblpurchases values (5, 4, 50);
insert into #tblpurchases values (6, 3, 250);
insert into #tblpurchases values (7, 6, 700);
insert into #tblpurchases values (8, 2, 30);
insert into #tblpurchases values (9, 1, 310);
insert into #tblpurchases values (10, 4, 25);
WITH CTE AS(
select c.id,c.customername from #tblcustomers c
)
Select c.id,c.customername,(Select SUM(ISNULL(P.price,0)) from #tblpurchases P
WHERE P.customerid = C.id) AS Price from CTE c

SQL Inner/Sub group wise Query for a specific scenario

I have a table as below
Schema: ID | Category | Keyword | Bid Price
Write a sql to fetch out top 5 keywords based on the bid price per category.
Details:
Table definition considered on oracle 10.x:
create table test (
ID number,
Category varchar (20),
Keyword varchar (20),
BidPrice number
);
Data:
insert into test values (1, 'Category-A', 'Keyword-A1', 110);
insert into test values (2, 'Category-A', 'Keyword-A2', 121);
insert into test values (3, 'Category-A', 'Keyword-A3', 130);
insert into test values (4, 'Category-A', 'Keyword-A4', 125);
insert into test values (5, 'Category-A', 'Keyword-A5', 115);
insert into test values (6, 'Category-A', 'Keyword-A6', 133);
insert into test values (7, 'Category-B', 'Keyword-B1', 105);
insert into test values (8, 'Category-B', 'Keyword-B2', 111);
insert into test values (9, 'Category-B', 'Keyword-B3', 108);
insert into test values (10, 'Category-B', 'Keyword-B4', 128);
insert into test values (11, 'Category-B', 'Keyword-B5', 144);
insert into test values (12, 'Category-B', 'Keyword-B6', 101);
insert into test values (13, 'Category-C', 'Keyword-C1', 150);
insert into test values (14, 'Category-C', 'Keyword-C2', 137);
insert into test values (15, 'Category-C', 'Keyword-C3', 126);
insert into test values (16, 'Category-C', 'Keyword-C4', 121);
insert into test values (17, 'Category-C', 'Keyword-C5', 112);
insert into test values (18, 'Category-C', 'Keyword-C6', 118);
Output expected:
KEYWORD CATEGORY BIDPRICE
-------------- ------------ ----------
Keyword-A6 Category-A 133
Keyword-A3 Category-A 130
Keyword-A4 Category-A 125
Keyword-A2 Category-A 121
Keyword-A5 Category-A 115
Keyword-B5 Category-B 144
Keyword-B4 Category-B 128
Keyword-B2 Category-B 111
Keyword-B3 Category-B 108
Keyword-B1 Category-B 105
Keyword-C1 Category-C 150
Keyword-C2 Category-C 137
Keyword-C3 Category-C 126
Keyword-C4 Category-C 121
Keyword-C6 Category-C 118
Note: Answer has to be only in SQL without use of any Oracle or database specific function.
try this:
select KEYWORD, CATEGORY ,BIDPRICE
from
(
select KEYWORD, CATEGORY ,BIDPRICE ,
ROW_NUMBER() over (partition by Category order by BidPrice desc) as rn
from test
) a
where a.rn <= 5;
Sql fiddle demo
make use of ROW_NUMBER()
SELECT KEYWORD ,CATEGORY, BIDPRICE
FROM
(
SELECT KEYWORD ,CATEGORY, BIDPRICE,
ROW_NUMBER() OVER (PARTITION BY CATEGORY ORDER BY BIDPRICE DESC) rn
FROM test
) a
WHERE rn <= 5
ORDER BY CATEGORY, BIDPRICE DESC
SQLFiddle Demo
I made this query but it is leaving the 6th row if it is biggest. Can any one help on this?
select a.keyword, a.category, a.bidprice
from
test a,
(
select b.id, b.category
from test b
where (select distinct(c.category) from test c where b.category=c.category) = b.category
) xx
where a.id in (select ss.id from test ss where a.category=ss.category and rownum<=5)
group by a.category, a.bidprice, a.keyword
order by a.category, a.bidprice desc;
Guys,
I solved it, please consider this:
select a.keyword, a.category, a.bidprice
from
test a,
(
select b.id, b.category
from test b
where (select distinct(c.category) from test c where b.category=c.category) = b.category
order by b.bidprice desc
) xx
where a.id in (
select id
from (select dd.id, dd.category from test dd order by dd.bidprice desc) ss
where a.category=ss.category
and rownum<=5
)
group by a.category, a.bidprice, a.keyword
order by a.category, a.bidprice desc;

How do I sort results from a nested select while keeping the rollup on the last row?

How do I sort the results into the following example by the sellers name while keeping the rollup at the bottom?
Since the the grouping is applied to the nested SELECT I can't use ORDER BY and since the grouping isn't applied at the top level I can't use the GROUPING either.
Click here to see the working example in SQL Fiddle.
CREATE TABLE Sales
(
SellerID INT
, StoreID INT
, Price MONEY
);
CREATE TABLE Sellers
(
SellerID INT
, Name VARCHAR(50)
)
INSERT INTO Sales VALUES
(1, 1, 100),
(1, 1, 100),
(1, 1, 100),
(2, 2, 200),
(2, 2, 200),
(3, 2, 250),
(3, 2, 250),
(3, 2, 250),
(3, 2, 250);
INSERT INTO Sellers VALUES
(1, 'C. Thirdplace'),
(2, 'A. Firstplace'),
(3, 'B. Secondplace');
SELECT s.Name AS Seller_Name
, x.TotalSales AS Total_Sales
FROM
(
SELECT s.SellerID AS SellerID
, SUM(s.Price) AS TotalSales
FROM Sales s
GROUP BY s.SellerID
WITH ROLLUP
) x
LEFT JOIN Sellers s
ON s.SellerID = x.SellerID;
Which produces the following result:
SELLER_NAME TOTAL_SALES
--------------- -----------
C. Thirdplace 300
A. Firstplace 400
B. Secondplace 1000
(null) 1700
ORDER BY
CASE WHEN seller_name IS NULL THEN 1 ELSE 0 END,
seller_name